diff --git a/include/actions/AddVectorTransferAction.h b/include/actions/AddVectorTransferAction.h new file mode 100644 index 00000000..1457d6bc --- /dev/null +++ b/include/actions/AddVectorTransferAction.h @@ -0,0 +1,227 @@ +#pragma once + +#include "MooseObjectAction.h" +#include "AuxiliarySystem.h" + +class AddVectorTransferAction : public MooseObjectAction +{ +public: + static InputParameters validParams(); + + AddVectorTransferAction(const InputParameters & params); + + virtual void act() override; + +protected: + /** + * Returns a shared pointer to or from the multiapp. + */ + const std::shared_ptr getFromMultiApp() const; + const std::shared_ptr getToMultiApp() const; + + /** + * Returns to/from problem variable names. + */ + const std::vector & getFromVarNames() const; + const std::vector & getToVarNames() const; + + const std::vector & getFromVarNamesConverted(); + const std::vector & getToVarNamesConverted(); + + /** + * An enumeration used internally to specify the component of a vector variable. + */ + enum class VectorComponent + { + X, + Y, + Z + }; + + /** + * An enumeration used to specify the auxkernel to build. + */ + enum class VectorAuxKernelType + { + PREPARE_VECTOR_FOR_TRANSFER, + RECOVER_VECTOR_POST_TRANSFER + }; + + /** + * Finds the FEProblemBase depending on the direction. + */ + FEProblemBase & getFromProblem() const; + FEProblemBase & getToProblem() const; + + /** + * Returns references to the auxsystem. + */ + AuxiliarySystem & getFromAuxSystem() const; + AuxiliarySystem & getToAuxSystem() const; + + /** + * Adds a vector auxkernel to the problem. + */ + void + addVectorAuxKernel(FEProblemBase & problem, std::string & vector_name, VectorAuxKernelType type); + + /** + * This method is called internally to locate all vector variables. For each vector variable + * it locates, it will create standard scalar variables. When the methods getFromVarNames() + * and getToVarNames() are called, they will return a vector containing only the standard + * variable names. + */ + void convertAllVariables(); + + /** + * This method will iterate through the variable names. If the variable associated with the name + * happens to be a vector variable, the standard variables for its components will be created. + * Returns a vector containing the updated variable names (adding all new standard variables and + * removing any vector variables). + */ + template + std::vector + convertVariables(FEProblemBase & problem, + std::vector & input_variable_names); + + /** + * This method verifies that source_type is a valid parameter. If it is and there is at least one + * vector variable supplied then we need to duplicate its source type for the new standard + * variable components. + */ + void convertSourceTypes(); + + /** + * Returns true is "source_type" is a valid parameter. + */ + bool hasSourceTypesParameter() const; + + /** + * Returns a reference to a vector of converted source types. + */ + std::vector & getSourceTypeConverted(); + + /** + * Returns all vector source variable names. + */ + std::set & getVectorSourceNames(); + + /** + * Returns true if variable name corresponds to a source vector variable. + */ + bool isSourceVectorVariable(const std::string & var_name); + + /** + * Creates component standard variables for the x, y and z components of a vector variable. + */ + void buildVectorComponents(FEProblemBase & problem, MooseVariableFEBase & vector_variable); + + /** + * Returns the extension for a given vector component. + */ + std::string buildVectorComponentExtension(VectorComponent component) const; + /** + * Creates the FEType of a variable corresponding to a component of a vector variable. + */ + InputParameters buildInputParametersForComponents(FEProblemBase & problem, + MooseVariableFEBase & vector_variable) const; + + /** + * Check whether the variable is a vector variable of the supported family/order. + */ + bool isSupportedVectorVariable(MooseVariableFEBase & vector_variable) const; + + /** + * Check whether the component variable is of a valid family. + */ + bool isSupportedComponentVariable(MooseVariableFEBase & variable) const; + + /** + * Checks whether a vector variable is compatible with a component variable. + */ + bool areCompatibleVariables(MooseVariableFEBase & vector_variable, + MooseVariableFEBase & component_variable) const; + + bool isPushTransfer() const; + bool isPullTransfer() const; + bool isSupportedTransfer() const; + + /** + * Helper methods. + */ + MooseVariableFEBase & + getVariable(FEProblemBase & problem, + std::string & variable_name, + Moose::VarFieldType type = Moose::VarFieldType::VAR_FIELD_ANY) const; + + /** + * Returns components of the enum class. This allows iterating over the components. + */ + std::array getAllComponents() const; + + /** + * Creates the name of the variable corresponding to a component of a vector variable. + */ + inline std::string buildVectorComponentName(const std::string & vector_name, + VectorComponent component) const; + + /** + * Creates the type name of the transfer suitable for vector variables. + */ + inline std::string buildVectorTransferTypeName(const std::string & transfer_type) const; + + /** + * Returns family/order of variable. + */ + inline libMesh::FEFamily getVariableFamily(const MooseVariableFEBase & variable) const; + inline libMesh::Order getVariableOrder(const MooseVariableFEBase & variable) const; + +private: + // Names of all source vector variables. + std::set _vector_source_names; + + // New variable names. + std::vector _from_var_names_converted; + std::vector _to_var_names_converted; + + // New source types (if present). + std::vector _source_type_converted; + + bool _has_converted_variables; + bool _has_converted_source_types; +}; + +inline std::string +AddVectorTransferAction::buildVectorComponentName(const std::string & vector_name, + VectorComponent component) const +{ + return (vector_name + buildVectorComponentExtension(component)); +} + +inline std::string +AddVectorTransferAction::buildVectorTransferTypeName(const std::string & transfer_type) const +{ + return (transfer_type + "Vector"); +} + +inline std::array +AddVectorTransferAction::getAllComponents() const +{ + + std::array components = { + VectorComponent::X, VectorComponent::Y, VectorComponent::Z}; + + return components; +} + +inline libMesh::FEFamily +AddVectorTransferAction::getVariableFamily(const MooseVariableFEBase & variable) const +{ + return variable.feType().family; +} + +inline libMesh::Order +AddVectorTransferAction::getVariableOrder(const MooseVariableFEBase & variable) const +{ + return variable.order(); +} \ No newline at end of file diff --git a/include/auxkernels/VectorVariableFromComponentsAux.h b/include/auxkernels/VectorVariableFromComponentsAux.h index 71c4d47a..4470e6bc 100644 --- a/include/auxkernels/VectorVariableFromComponentsAux.h +++ b/include/auxkernels/VectorVariableFromComponentsAux.h @@ -12,18 +12,13 @@ class VectorVariableFromComponentsAux : public WritableVectorAuxKernel VectorVariableFromComponentsAux(const InputParameters & parameters); -protected: - virtual void compute() override; - - MooseVariable & _component_x; - MooseVariable & _component_y; - MooseVariable & _component_z; + void compute() override; - const Order _vector_order; - const FEFamily _vector_family; - -private: - void checkVectorVariable() const; - void checkVectorComponents() const; - void checkVectorComponent(const MooseVariable & component_variable) const; +protected: + /** + * Non-writable references to the component variables. + */ + const MooseVariable & _component_x; + const MooseVariable & _component_y; + const MooseVariable & _component_z; }; diff --git a/include/auxkernels/VectorVariableToComponentsAux.h b/include/auxkernels/VectorVariableToComponentsAux.h index 5f98c59c..6c9cf57f 100644 --- a/include/auxkernels/VectorVariableToComponentsAux.h +++ b/include/auxkernels/VectorVariableToComponentsAux.h @@ -1,17 +1,24 @@ #pragma once -#include "VectorVariableFromComponentsAux.h" +#include "WritableVectorAuxKernel.h" /** * Set 3 standard variables from a vector variable. */ -class VectorVariableToComponentsAux : public VectorVariableFromComponentsAux +class VectorVariableToComponentsAux : public WritableVectorAuxKernel { public: static InputParameters validParams(); VectorVariableToComponentsAux(const InputParameters & parameters); + void compute() override; + protected: - virtual void compute() override; + /** + * Writable references to component variables. + */ + MooseVariable & _component_x; + MooseVariable & _component_y; + MooseVariable & _component_z; }; diff --git a/include/auxkernels/WritableVectorAuxKernel.h b/include/auxkernels/WritableVectorAuxKernel.h index ba77bc5e..72033592 100644 --- a/include/auxkernels/WritableVectorAuxKernel.h +++ b/include/auxkernels/WritableVectorAuxKernel.h @@ -13,12 +13,41 @@ class WritableVectorAuxKernel : public VectorAuxKernel public: static InputParameters validParams() { return VectorAuxKernel::validParams(); } - WritableVectorAuxKernel(const InputParameters & parameters) : VectorAuxKernel(parameters) {} + WritableVectorAuxKernel(const InputParameters & parameters); protected: // NB: not used. virtual RealVectorValue computeValue() override { mooseError("Unused"); } - // NB: see "writableVariable" method defined in "Coupleable.h". - MooseVariable & writableVariable(const std::string & var_name, unsigned int comp = 0); + const Order _vector_order; + const FEFamily _vector_family; + + /** + * This method is based on "writableVariable" defined in "Coupleable.h". Due to a limitation of + * MOOSE it is not possible to call this from a VectorAuxKernel class. + * + * NB: only a single AuxKernel can obtain a writable reference to a variable. This becomes a + * problem for transfers where we need to push and pull the same variable using the auxkernels + * inheriting from this class. + * + * For VectorVariableToComponentsAux, we require writable references. + */ + MooseVariable & getWritableCoupledVariable(const std::string & var_name, unsigned int comp = 0); + + /** + * Returns a const-qualified reference to the coupled variable. This is required for + * VectorVariableFromComponentsAux since we don't need to update the values of the component + * variables. + */ + const MooseVariable & getNonWritableCoupledVariable(const std::string & var_name, + unsigned int comp = 0); + + /** + * Check component variables are consistent with the vector variable. + */ + void checkVectorVariable() const; + void checkVectorComponent(const MooseVariable & component_variable) const; + void checkVectorComponents(const MooseVariable & component_x, + const MooseVariable & component_y, + const MooseVariable & component_z) const; }; diff --git a/include/base/ApolloVectorTransferFlags.h b/include/base/ApolloVectorTransferFlags.h new file mode 100644 index 00000000..0448e755 --- /dev/null +++ b/include/base/ApolloVectorTransferFlags.h @@ -0,0 +1,9 @@ +#pragma once + +#include "Moose.h" + +namespace Apollo +{ +extern const ExecFlagType EXEC_PREPARE_VECTOR_FOR_TRANSFER; +extern const ExecFlagType EXEC_RECOVER_VECTOR_POST_TRANSFER; +} \ No newline at end of file diff --git a/include/transfers/MultiAppGeneralVectorTransfer.h b/include/transfers/MultiAppGeneralVectorTransfer.h new file mode 100644 index 00000000..eabc40bb --- /dev/null +++ b/include/transfers/MultiAppGeneralVectorTransfer.h @@ -0,0 +1,41 @@ +#pragma once + +/** + * Include headers of all MultiApp Transfers we would like. + */ +#include "AuxKernel.h" +#include "AuxiliarySystem.h" + +// Forwards declaration. +template +class MultiAppVectorTransferTemplate; + +class MultiAppGeneralFieldNearestLocationTransfer; +class MultiAppGeneralFieldShapeEvaluationTransfer; + +/** + * Create all transfer types using template here. Don't forget to register them in .C file. + */ +typedef MultiAppVectorTransferTemplate + MultiAppGeneralFieldNearestLocationTransferVector; +typedef MultiAppVectorTransferTemplate + MultiAppGeneralFieldShapeEvaluationTransferVector; + +template +class MultiAppVectorTransferTemplate : public MultiAppTransferClassType +{ +public: + static InputParameters validParams(); + + MultiAppVectorTransferTemplate(const InputParameters & parameters); + + void execute() override final; + +protected: + inline AuxiliarySystem & getFromAuxSystem() const { return _from_aux_system; } + inline AuxiliarySystem & getToAuxSystem() const { return _to_aux_system; } + +private: + AuxiliarySystem & _from_aux_system; + AuxiliarySystem & _to_aux_system; +}; \ No newline at end of file diff --git a/src/actions/AddVectorTransferAction.C b/src/actions/AddVectorTransferAction.C new file mode 100644 index 00000000..d23c09c4 --- /dev/null +++ b/src/actions/AddVectorTransferAction.C @@ -0,0 +1,542 @@ +#include "AddVectorTransferAction.h" +#include "AuxiliarySystem.h" +#include "AuxKernel.h" +#include "FEProblem.h" + +#include "ApolloVectorTransferFlags.h" + +registerMooseAction("MooseApp", AddVectorTransferAction, "add_vector_transfer"); + +InputParameters +AddVectorTransferAction::validParams() +{ + InputParameters params = MooseObjectAction::validParams(); + params.addClassDescription("Add a Transfer object that can handle vectors to the simulation."); + return params; +} + +AddVectorTransferAction::AddVectorTransferAction(const InputParameters & params) + : MooseObjectAction(params) +{ +} + +void +AddVectorTransferAction::act() +{ + // Modify the input parameters. + if (hasSourceTypesParameter()) + { + getObjectParams().set>("source_type") = getSourceTypeConverted(); + } + + // NB: set at end in case we need to call getTo(From)VarNames(). + getObjectParams().set>("source_variable") = getFromVarNamesConverted(); + getObjectParams().set>("variable") = getToVarNamesConverted(); + + // Add required pointers to the auxiliary systems of both the fromProblem and the toProblem. + getObjectParams().set("from_aux_system") = &getFromAuxSystem(); + getObjectParams().set("to_aux_system") = &getToAuxSystem(); + + // Create the transfer using the wrapped transfer (which modifies the execute method). + _problem->addTransfer(buildVectorTransferTypeName(_type), _name, getObjectParams()); +} + +const std::shared_ptr +AddVectorTransferAction::getFromMultiApp() const +{ + if (getObjectParams().isParamValid("from_multi_app")) + { + return _problem->getMultiApp(getObjectParams().get("from_multi_app")); + } + + return nullptr; +} + +const std::shared_ptr +AddVectorTransferAction::getToMultiApp() const +{ + if (getObjectParams().isParamValid("to_multi_app")) + { + return _problem->getMultiApp(getObjectParams().get("to_multi_app")); + } + + return nullptr; +} + +const std::vector & +AddVectorTransferAction::getFromVarNames() const +{ + return getObjectParams().get>("source_variable"); +} + +const std::vector & +AddVectorTransferAction::getToVarNames() const +{ + return getObjectParams().get>("variable"); +} + +const std::vector & +AddVectorTransferAction::getFromVarNamesConverted() +{ + if (!_has_converted_variables) + { + convertAllVariables(); + } + + return _from_var_names_converted; +} + +const std::vector & +AddVectorTransferAction::getToVarNamesConverted() +{ + if (!_has_converted_variables) + { + convertAllVariables(); + } + + return _to_var_names_converted; +} + +std::set & +AddVectorTransferAction::getVectorSourceNames() +{ + if (!_has_converted_variables) + { + convertAllVariables(); // Must be run first! + } + + return _vector_source_names; +} + +bool +AddVectorTransferAction::isSourceVectorVariable(const std::string & var_name) +{ + return getVectorSourceNames().count(var_name); +} + +FEProblemBase & +AddVectorTransferAction::getToProblem() const +{ + if (isPullTransfer()) // subapp (FROM) --> master. + { + auto & subapp = getFromMultiApp(); + + return subapp->problemBase(); + } + else if (isPushTransfer()) // master (FROM) --> subapp + { + auto & subapp = getToMultiApp(); + + for (unsigned int iapp = 0; iapp < subapp->numGlobalApps(); iapp++) + { + if (subapp->hasLocalApp(iapp)) + { + return subapp->appProblemBase(iapp); + } + } + } + + mooseError("The FEProblemBase could not be located."); +} + +FEProblemBase & +AddVectorTransferAction::getFromProblem() const +{ + if (isPullTransfer()) // subapp --> master (TO). + { + auto & subapp = getFromMultiApp(); + + for (unsigned int iapp = 0; iapp < subapp->numGlobalApps(); iapp++) + { + if (subapp->hasLocalApp(iapp)) + { + return subapp->appProblemBase(iapp); + } + } + } + else if (isPushTransfer()) // master --> subapp (TO). + { + auto & subapp = getToMultiApp(); + + return subapp->problemBase(); + } + + mooseError("The FEProblemBase could not be located."); +} + +AuxiliarySystem & +AddVectorTransferAction::getFromAuxSystem() const +{ + return getFromProblem().getAuxiliarySystem(); +} + +AuxiliarySystem & +AddVectorTransferAction::getToAuxSystem() const +{ + return getToProblem().getAuxiliarySystem(); +} + +void +AddVectorTransferAction::addVectorAuxKernel(FEProblemBase & problem, + std::string & vector_name, + VectorAuxKernelType type) +{ + std::string aux_kernel_name; + std::string unique_aux_kernel_name; + + ExecFlagType exec_flag; + + switch (type) + { + case VectorAuxKernelType::RECOVER_VECTOR_POST_TRANSFER: + aux_kernel_name = "VectorVariableFromComponentsAux"; + unique_aux_kernel_name = vector_name + "_from_components"; + exec_flag = Apollo::EXEC_RECOVER_VECTOR_POST_TRANSFER; + break; + case VectorAuxKernelType::PREPARE_VECTOR_FOR_TRANSFER: + aux_kernel_name = "VectorVariableToComponentsAux"; + unique_aux_kernel_name = vector_name + "_to_components"; + exec_flag = Apollo::EXEC_PREPARE_VECTOR_FOR_TRANSFER; + break; + default: + mooseError("Unsupported vector auxkernel type."); + break; + } + + // NB: we need to use the correct factory! + auto params = problem.getMooseApp().getFactory().getValidParams(aux_kernel_name); + + params.set("variable") = vector_name; + params.set>("component_x") = { + buildVectorComponentName(vector_name, VectorComponent::X)}; + params.set>("component_y") = { + buildVectorComponentName(vector_name, VectorComponent::Y)}; + params.set>("component_z") = { + buildVectorComponentName(vector_name, VectorComponent::Z)}; + + // Set execution flag. This will prevent the auxkernels being called elsewhere. The auxkernels + // will be triggered in the template transfer class which wraps around the existing transfer + // class. + params.set("execute_on") = exec_flag; + problem.addAuxKernel(aux_kernel_name, unique_aux_kernel_name, params); +} + +void +AddVectorTransferAction::convertAllVariables() +{ + // Check if this method has been called before. + if (_has_converted_variables) + { + return; + } + + _has_converted_variables = true; + + // Extract the to/from variable names from the base class. + std::vector from_var_names = getFromVarNames(); + std::vector to_var_names = getToVarNames(); + + // Locate any vector variables. For these variables, create the corrresponding standard + // variables for their components. Return updated vector strings which contain the new + // standard variables but exclude the vector variables. + FEProblemBase & from_problem = getFromProblem(); + FEProblemBase & to_problem = getToProblem(); + + _to_var_names_converted = convertVariables(to_problem, to_var_names); + _from_var_names_converted = convertVariables(from_problem, from_var_names); +} + +bool +AddVectorTransferAction::hasSourceTypesParameter() const +{ + return getObjectParams().isParamValid("source_type"); +} + +std::vector & +AddVectorTransferAction::getSourceTypeConverted() +{ + if (!hasSourceTypesParameter()) + { + mooseError("No 'source_type' parameter exists for this transfer."); + } + + if (!_has_converted_source_types) + { + convertSourceTypes(); + } + + return _source_type_converted; +} + +void +AddVectorTransferAction::convertSourceTypes() +{ + // Safety check. Ensure that the 'source_type' parameter exists. + if (!hasSourceTypesParameter()) + { + mooseError("No 'source_type' parameter exists for this transfer."); + } + + // Has method been called before? + if (_has_converted_source_types) + { + return; + } + + _has_converted_source_types = true; + + // 1. Get source types: + const std::vector & current_source_types = + getObjectParams().get>("source_type"); + + // 2. If there are no vector source variables, then set to the current source type. + // NB: ensure we call accessor. + if (getVectorSourceNames().empty()) + { + _source_type_converted = current_source_types; + return; + } + + // 3. Iterate over original variable names. + std::vector new_source_types; + + int isource = 0; + for (auto & var_name : getFromVarNames()) + { + auto source_type = current_source_types[isource++]; + + _source_type_converted.push_back(source_type); + + if (isSourceVectorVariable(var_name)) + { + _source_type_converted.push_back(source_type); // y component + _source_type_converted.push_back(source_type); // z component + } + } + + _source_type_converted.shrink_to_fit(); +} + +template +std::vector +AddVectorTransferAction::convertVariables(FEProblemBase & problem, + std::vector & input_variable_names) +{ + std::vector output_variable_names; + + for (auto & variable_name : input_variable_names) + { + MooseVariableFEBase & variable = getVariable(problem, variable_name); + + if (!isSupportedVectorVariable(variable)) + { + // Nothing to do here. Pushback variable. + output_variable_names.push_back(variable_name); + continue; + } + + // Create corresponding standard variables for components. Add to output array. + buildVectorComponents(problem, variable); + + auto component_x_name = buildVectorComponentName(variable_name, VectorComponent::X); + auto component_y_name = buildVectorComponentName(variable_name, VectorComponent::Y); + auto component_z_name = buildVectorComponentName(variable_name, VectorComponent::Z); + + output_variable_names.push_back(component_x_name); + output_variable_names.push_back(component_y_name); + output_variable_names.push_back(component_z_name); + + /** + * Case 1: "from problem" --> Update vector components. These will be transferred. + * Case 2: "to problem" --> Received vector components. Rebuild vector from components. + */ + if (&problem == &getFromProblem()) + { + // Add vector name to set for checking later. + _vector_source_names.insert(variable_name); + + addVectorAuxKernel(problem, variable_name, VectorAuxKernelType::PREPARE_VECTOR_FOR_TRANSFER); + } + else if (&problem == &getToProblem()) + { + addVectorAuxKernel(problem, variable_name, VectorAuxKernelType::RECOVER_VECTOR_POST_TRANSFER); + } + else + { + mooseError("Unknown FEProblemBase."); + } + } + + output_variable_names.shrink_to_fit(); + + return output_variable_names; +} + +void +AddVectorTransferAction::buildVectorComponents(FEProblemBase & problem, + MooseVariableFEBase & vector_variable) +{ + // Safety check. + if (!isSupportedVectorVariable(vector_variable)) + { + mooseError("The variable '", vector_variable.name(), "' is not a supported vector variable."); + } + + // Iterate over all components. + for (auto component : getAllComponents()) + { + // Create vector variable component name. + std::string component_name = buildVectorComponentName(vector_variable.name(), component); + + // Does the component exist? If so, is it of the correct type. If it is not compatible then we + // have a problem. + bool component_already_exists = problem.hasVariable(component_name); + + if (component_already_exists) + { + // Component already exists! Check that it is compatible with the vector variable and emit a + // warning that the variable already exists so we don't blindly overwrite the user's values. + MooseVariableFEBase & component_variable = getVariable(problem, component_name); + + if (areCompatibleVariables(vector_variable, component_variable)) + { + mooseWarning("Found existing variable '", + component_name, + "' which is compatible with vector '", + vector_variable.name(), + "'."); + } + else + { + mooseError("Found existing variable '", + component_name, + "' which is incompatible with vector '", + vector_variable.name(), + "'."); + } + } + else + { + // Attempt to add the auxiliary variable. + auto component_parameters = buildInputParametersForComponents(problem, vector_variable); + + problem.addAuxVariable("MooseVariable", component_name, component_parameters); + } + } +} + +std::string +AddVectorTransferAction::buildVectorComponentExtension(VectorComponent component) const +{ + std::string extension; + + switch (component) + { + case VectorComponent::X: + extension = "_x"; + break; + case VectorComponent::Y: + extension = "_y"; + break; + case VectorComponent::Z: + extension = "_z"; + break; + default: + mooseError("An unsupported vector component was detected."); + break; + } + + return extension; +} + +InputParameters +AddVectorTransferAction::buildInputParametersForComponents( + FEProblemBase & problem, + MooseVariableFEBase & vector_variable) const +{ + if (!isSupportedVectorVariable(vector_variable)) + { + mooseError("'", vector_variable.name(), "' is not a supported vector variable."); + } + + const auto vector_order = getVariableOrder(vector_variable); + const auto vector_family = getVariableFamily(vector_variable); + + InputParameters params = problem.getMooseApp().getFactory().getValidParams("MooseVariable"); + + // Should be same order as vector variable but obviously of a different family. + params.set("order") = Utility::enum_to_string(OrderWrapper{vector_order}); + params.set("family") = (vector_family == LAGRANGE_VEC ? "LAGRANGE" : "MONOMIAL"); + + return params; +} + +bool +AddVectorTransferAction::isSupportedVectorVariable(MooseVariableFEBase & variable) const +{ + const auto family = getVariableFamily(variable); + const auto order = getVariableOrder(variable); + + return (family == LAGRANGE_VEC || (family == MONOMIAL_VEC && order == CONSTANT)); +} + +bool +AddVectorTransferAction::isSupportedComponentVariable(MooseVariableFEBase & variable) const +{ + const auto family = getVariableFamily(variable); + const auto order = getVariableOrder(variable); + + return (family == LAGRANGE || (family == MONOMIAL && order == CONSTANT)); +} + +bool +AddVectorTransferAction::areCompatibleVariables(MooseVariableFEBase & vector_variable, + MooseVariableFEBase & component_variable) const +{ + bool supported_vector = isSupportedVectorVariable(vector_variable); + bool supported_component = isSupportedComponentVariable(component_variable); + + if (!supported_vector || !supported_component) + { + return false; + } + + const auto component_family = component_variable.feType().family; + const auto component_order = component_variable.order(); + + const auto vector_family = vector_variable.feType().family; + const auto vector_order = vector_variable.order(); + + bool compatibleFamilies = (component_family == LAGRANGE && vector_family == LAGRANGE_VEC) || + (component_family == MONOMIAL && vector_family == MONOMIAL_VEC); + + bool compatibleOrders = (component_order == vector_order); + + return (compatibleFamilies && compatibleOrders); +} + +bool +AddVectorTransferAction::isPushTransfer() const +{ + return getObjectParams().isParamValid("to_multi_app"); +} + +bool +AddVectorTransferAction::isPullTransfer() const +{ + return getObjectParams().isParamValid("from_multi_app"); +} + +bool +AddVectorTransferAction::isSupportedTransfer() const +{ + return (isPushTransfer() || isPullTransfer()); +} + +MooseVariableFEBase & +AddVectorTransferAction::getVariable(FEProblemBase & problem, + std::string & variable_name, + Moose::VarFieldType type) const +{ + return problem.getVariable(0, variable_name, Moose::VarKindType::VAR_ANY, type); +} diff --git a/src/auxkernels/VectorVariableFromComponentsAux.C b/src/auxkernels/VectorVariableFromComponentsAux.C index 05febe92..c019d7b4 100644 --- a/src/auxkernels/VectorVariableFromComponentsAux.C +++ b/src/auxkernels/VectorVariableFromComponentsAux.C @@ -1,4 +1,5 @@ #include "VectorVariableFromComponentsAux.h" +#include "ApolloVectorTransferFlags.h" registerMooseObject("MooseApp", VectorVariableFromComponentsAux); @@ -7,6 +8,9 @@ VectorVariableFromComponentsAux::validParams() { InputParameters params = WritableVectorAuxKernel::validParams(); + ExecFlagEnum & exec = params.set("execute_on"); + exec.addAvailableFlags(Apollo::EXEC_RECOVER_VECTOR_POST_TRANSFER); + params.addRequiredCoupledVar("component_x", "The x-component of the vector variable."); params.addRequiredCoupledVar("component_y", "The y-component of the vector variable."); params.addRequiredCoupledVar("component_z", "The z-component of the vector variable."); @@ -18,63 +22,21 @@ VectorVariableFromComponentsAux::validParams() VectorVariableFromComponentsAux::VectorVariableFromComponentsAux(const InputParameters & parameters) : WritableVectorAuxKernel(parameters), - _component_x(writableVariable("component_x")), - _component_y(writableVariable("component_y")), - _component_z(writableVariable("component_z")), - _vector_order(_var.order()), - _vector_family(_var.feType().family) + _component_x(getNonWritableCoupledVariable("component_x")), + _component_y(getNonWritableCoupledVariable("component_y")), + _component_z(getNonWritableCoupledVariable("component_z")) { - checkVectorVariable(); - checkVectorComponents(); + checkVectorComponents(_component_x, _component_y, _component_z); } void VectorVariableFromComponentsAux::compute() { - _variable->setDofValue(_component_x.dofValues()[0], 0); - _variable->setDofValue(_component_y.dofValues()[0], 1); - _variable->setDofValue(_component_z.dofValues()[0], 2); -} - -void -VectorVariableFromComponentsAux::checkVectorVariable() const -{ - if (_vector_family != LAGRANGE_VEC && _vector_family != MONOMIAL_VEC) - { - mooseError("Only Lagrange and Monomial vectors are supported."); - } - - if (_vector_family == MONOMIAL_VEC && _vector_order != CONSTANT) - { - mooseError("Monomial vectors are supported only for constant order."); - } -} + Real value_x = _component_x.dofValues()[0]; + Real value_y = _component_y.dofValues()[0]; + Real value_z = _component_z.dofValues()[0]; -void -VectorVariableFromComponentsAux::checkVectorComponents() const -{ - checkVectorComponent(_component_x); - checkVectorComponent(_component_y); - checkVectorComponent(_component_z); + _variable->setDofValue(value_x, 0); + _variable->setDofValue(value_y, 1); + _variable->setDofValue(value_z, 2); } - -void -VectorVariableFromComponentsAux::checkVectorComponent( - const MooseVariable & component_variable) const -{ - auto component_order = component_variable.order(); - auto component_family = component_variable.feType().family; - - bool correct_family = ((component_family == LAGRANGE && _vector_family == LAGRANGE_VEC) || - (component_family == MONOMIAL && _vector_family == MONOMIAL_VEC)); - if (!correct_family) - { - mooseError("Component '", component_variable.name(), "' is of the incorrect family."); - } - - bool correct_order = (component_order == _vector_order); - if (!correct_order) - { - mooseError("Component '", component_variable.name(), "' has a different order to the vector."); - } -} \ No newline at end of file diff --git a/src/auxkernels/VectorVariableToComponentsAux.C b/src/auxkernels/VectorVariableToComponentsAux.C index 5b09fd86..b4d2a90a 100644 --- a/src/auxkernels/VectorVariableToComponentsAux.C +++ b/src/auxkernels/VectorVariableToComponentsAux.C @@ -1,11 +1,19 @@ #include "VectorVariableToComponentsAux.h" +#include "ApolloVectorTransferFlags.h" registerMooseObject("MooseApp", VectorVariableToComponentsAux); InputParameters VectorVariableToComponentsAux::validParams() { - InputParameters params = VectorVariableFromComponentsAux::validParams(); + InputParameters params = WritableVectorAuxKernel::validParams(); + + ExecFlagEnum & exec = params.set("execute_on"); + exec.addAvailableFlags(Apollo::EXEC_PREPARE_VECTOR_FOR_TRANSFER); + + params.addRequiredCoupledVar("component_x", "The x-component of the vector variable."); + params.addRequiredCoupledVar("component_y", "The y-component of the vector variable."); + params.addRequiredCoupledVar("component_z", "The z-component of the vector variable."); params.addClassDescription("Extract the components of a vector."); @@ -13,8 +21,12 @@ VectorVariableToComponentsAux::validParams() } VectorVariableToComponentsAux::VectorVariableToComponentsAux(const InputParameters & parameters) - : VectorVariableFromComponentsAux(parameters) + : WritableVectorAuxKernel(parameters), + _component_x(getWritableCoupledVariable("component_x")), + _component_y(getWritableCoupledVariable("component_y")), + _component_z(getWritableCoupledVariable("component_z")) { + checkVectorComponents(_component_x, _component_y, _component_z); } void diff --git a/src/auxkernels/WritableVectorAuxKernel.C b/src/auxkernels/WritableVectorAuxKernel.C index 8fafacba..3147f74c 100644 --- a/src/auxkernels/WritableVectorAuxKernel.C +++ b/src/auxkernels/WritableVectorAuxKernel.C @@ -2,13 +2,76 @@ registerMooseObject("MooseApp", WritableVectorAuxKernel); +WritableVectorAuxKernel::WritableVectorAuxKernel(const InputParameters & parameters) + : VectorAuxKernel(parameters), _vector_order(_var.order()), _vector_family(_var.feType().family) +{ + checkVectorVariable(); +} + +const MooseVariable & +WritableVectorAuxKernel::getNonWritableCoupledVariable(const std::string & var_name, + unsigned int comp) +{ + const MooseVariable * var = getVar(var_name, comp); + if (!var) + { + mooseError("Could not find coupled variable with name '", var_name, "'."); + } + + return *var; +} + MooseVariable & -WritableVectorAuxKernel::writableVariable(const std::string & var_name, unsigned int comp) +WritableVectorAuxKernel::getWritableCoupledVariable(const std::string & var_name, unsigned int comp) { - auto * var = dynamic_cast(getVar(var_name, comp)); + auto * var = getVar(var_name, comp); // Make sure only one object can access a variable. checkWritableVar(var); return *var; } + +void +WritableVectorAuxKernel::checkVectorVariable() const +{ + if (_vector_family != LAGRANGE_VEC && _vector_family != MONOMIAL_VEC) + { + mooseError("Only Lagrange and Monomial vectors are supported."); + } + + if (_vector_family == MONOMIAL_VEC && _vector_order != CONSTANT) + { + mooseError("Monomial vectors are supported only for constant order."); + } +} + +void +WritableVectorAuxKernel::checkVectorComponent(const MooseVariable & component_variable) const +{ + auto component_order = component_variable.order(); + auto component_family = component_variable.feType().family; + + bool correct_family = ((component_family == LAGRANGE && _vector_family == LAGRANGE_VEC) || + (component_family == MONOMIAL && _vector_family == MONOMIAL_VEC)); + if (!correct_family) + { + mooseError("Component '", component_variable.name(), "' is of the incorrect family."); + } + + bool correct_order = (component_order == _vector_order); + if (!correct_order) + { + mooseError("Component '", component_variable.name(), "' has a different order to the vector."); + } +} + +void +WritableVectorAuxKernel::checkVectorComponents(const MooseVariable & component_x, + const MooseVariable & component_y, + const MooseVariable & component_z) const +{ + checkVectorComponent(component_x); + checkVectorComponent(component_y); + checkVectorComponent(component_z); +} diff --git a/src/base/ApolloApp.C b/src/base/ApolloApp.C index 11a47314..794c1ece 100644 --- a/src/base/ApolloApp.C +++ b/src/base/ApolloApp.C @@ -3,6 +3,9 @@ #include "AppFactory.h" #include "ModulesApp.h" #include "MooseSyntax.h" +#include "Transfer.h" +#include "MultiAppTransfer.h" +#include "MultiAppCopyTransfer.h" InputParameters ApolloApp::validParams() @@ -63,6 +66,13 @@ associateSyntaxInner(Syntax & syntax, ActionFactory & /*action_factory*/) addTaskDependency("add_elemental_field_variable", "add_mfem_fespaces"); addTaskDependency("add_kernel", "add_mfem_fespaces"); addTaskDependency("add_mfem_sources", "add_mfem_fespaces"); + + // Custom vector transfer + registerSyntaxTask("AddVectorTransferAction", "VectorTransfers/*", "add_vector_transfer"); + registerMooseObjectTask("add_vector_transfer", Transfer, false); + appendMooseObjectTask("add_vector_transfer", MultiAppTransfer); + appendMooseObjectTask("add_vector_transfer", MultiAppCopyTransfer); + addTaskDependency("add_transfer", "add_vector_transfer"); } void diff --git a/src/base/ApolloVectorTransferFlags.C b/src/base/ApolloVectorTransferFlags.C new file mode 100644 index 00000000..6983e769 --- /dev/null +++ b/src/base/ApolloVectorTransferFlags.C @@ -0,0 +1,8 @@ +#include "ApolloVectorTransferFlags.h" + +#include "ExecFlagRegistry.h" + +const ExecFlagType Apollo::EXEC_PREPARE_VECTOR_FOR_TRANSFER = + registerExecFlag("PREPARE_VECTOR_FOR_TRANSFER"); +const ExecFlagType Apollo::EXEC_RECOVER_VECTOR_POST_TRANSFER = + registerExecFlag("RECOVER_VECTOR_POST_TRANSFER"); \ No newline at end of file diff --git a/src/postprocessors/ElementVectorL2Difference.C b/src/postprocessors/ElementVectorL2Difference.C index a2b70acb..7a47903f 100644 --- a/src/postprocessors/ElementVectorL2Difference.C +++ b/src/postprocessors/ElementVectorL2Difference.C @@ -47,13 +47,15 @@ ElementVectorL2Difference::computeQpIntegral() return difference_vector.norm_sq(); // dot product of difference vector. } -void ElementVectorL2Difference::checkVectorVariables() const +void +ElementVectorL2Difference::checkVectorVariables() const { auto & coupled_vector_variables = getCoupledVectorMooseVars(); if (coupled_vector_variables.size() != 2) { - mooseError("There are ", coupled_vector_variables.size(), " coupled vector variables. Expected 2."); + mooseError( + "There are ", coupled_vector_variables.size(), " coupled vector variables. Expected 2."); } auto first = coupled_vector_variables[0]; diff --git a/src/transfers/MultiAppGeneralVectorTransfer.C b/src/transfers/MultiAppGeneralVectorTransfer.C new file mode 100644 index 00000000..4a0b7faa --- /dev/null +++ b/src/transfers/MultiAppGeneralVectorTransfer.C @@ -0,0 +1,55 @@ +#include "MultiAppGeneralVectorTransfer.h" +#include "AuxiliarySystem.h" + +#include "MultiAppGeneralFieldNearestLocationTransfer.h" +#include "MultiAppGeneralFieldShapeEvaluationTransfer.h" +#include "MultiAppCopyTransfer.h" + +#include "ApolloVectorTransferFlags.h" + +/** + * Register all Moose objects that we would like here. + */ +registerMooseObject("MooseApp", MultiAppGeneralFieldNearestLocationTransferVector); +registerMooseObject("MooseApp", MultiAppGeneralFieldShapeEvaluationTransferVector); + +template +InputParameters +MultiAppVectorTransferTemplate::validParams() +{ + InputParameters params = MultiAppTransferClassType::validParams(); + + params.addRequiredParam( + "from_aux_system", + "The auxiliary system for the problem we are transferrring variables from."); + params.addRequiredParam( + "to_aux_system", "The auxiliary system for the problem we are transferring variables to."); + + // Combine class description for original class with template class. + params.addClassDescription(params.getClassDescription() + " (allows vector variables)."); + + return params; +} + +template +MultiAppVectorTransferTemplate::MultiAppVectorTransferTemplate( + const InputParameters & parameters) + : MultiAppTransferClassType(parameters), + _from_aux_system(*parameters.get("from_aux_system")), + _to_aux_system(*parameters.get("to_aux_system")) +{ +} + +template +void +MultiAppVectorTransferTemplate::execute() +{ + // Update all components of the vector variables. + getFromAuxSystem().compute(Apollo::EXEC_PREPARE_VECTOR_FOR_TRANSFER); + + // Call execute on inherited class which will work on component variables. + MultiAppTransferClassType::execute(); + + // Rebuild all vector variables from their components. + getToAuxSystem().compute(Apollo::EXEC_RECOVER_VECTOR_POST_TRANSFER); +} diff --git a/test/tests/unit/transfers/push_pull_multi_element_order2_distributed_transfer_master.i b/test/tests/unit/transfers/push_pull_multi_element_order2_distributed_transfer_master.i index bb921238..acac57fc 100644 --- a/test/tests/unit/transfers/push_pull_multi_element_order2_distributed_transfer_master.i +++ b/test/tests/unit/transfers/push_pull_multi_element_order2_distributed_transfer_master.i @@ -48,7 +48,7 @@ [sub_app] type = TransientMultiApp positions = '0 0 0' - input_files = 'push_pull_multi_element_order2_transfer_sub_app.i' + input_files = 'push_pull_multi_element_order2_distributed_transfer_sub_app.i' execute_on = timestep_begin [] [] diff --git a/test/tests/unit/vector_transfers/gold/pull_lagrange_vector_nearest_location_transfer_master_out.csv b/test/tests/unit/vector_transfers/gold/pull_lagrange_vector_nearest_location_transfer_master_out.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/pull_lagrange_vector_nearest_location_transfer_master_out.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/pull_monomial_vector_nearest_location_transfer_master_out.csv b/test/tests/unit/vector_transfers/gold/pull_monomial_vector_nearest_location_transfer_master_out.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/pull_monomial_vector_nearest_location_transfer_master_out.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/push_lagrange_vector_nearest_location_transfer_master_out_sub_app0.csv b/test/tests/unit/vector_transfers/gold/push_lagrange_vector_nearest_location_transfer_master_out_sub_app0.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/push_lagrange_vector_nearest_location_transfer_master_out_sub_app0.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/push_monomial_vector_nearest_location_transfer_master_out_sub_app0.csv b/test/tests/unit/vector_transfers/gold/push_monomial_vector_nearest_location_transfer_master_out_sub_app0.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/push_monomial_vector_nearest_location_transfer_master_out_sub_app0.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/push_pull_lagrange_vector_nearest_location_transfer_master_out.csv b/test/tests/unit/vector_transfers/gold/push_pull_lagrange_vector_nearest_location_transfer_master_out.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/push_pull_lagrange_vector_nearest_location_transfer_master_out.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/push_pull_lagrange_vector_shape_evaluation_transfer_master_out.csv b/test/tests/unit/vector_transfers/gold/push_pull_lagrange_vector_shape_evaluation_transfer_master_out.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/push_pull_lagrange_vector_shape_evaluation_transfer_master_out.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/push_pull_monomial_vector_nearest_location_transfer_master_out.csv b/test/tests/unit/vector_transfers/gold/push_pull_monomial_vector_nearest_location_transfer_master_out.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/push_pull_monomial_vector_nearest_location_transfer_master_out.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/gold/push_pull_monomial_vector_shape_evaluation_transfer_master_out.csv b/test/tests/unit/vector_transfers/gold/push_pull_monomial_vector_shape_evaluation_transfer_master_out.csv new file mode 100644 index 00000000..f260eb1a --- /dev/null +++ b/test/tests/unit/vector_transfers/gold/push_pull_monomial_vector_shape_evaluation_transfer_master_out.csv @@ -0,0 +1,3 @@ +time,vector_l2_difference +0,0 +1,0 diff --git a/test/tests/unit/vector_transfers/pull_lagrange_vector_nearest_location_transfer_master.i b/test/tests/unit/vector_transfers/pull_lagrange_vector_nearest_location_transfer_master.i new file mode 100644 index 00000000..b1322716 --- /dev/null +++ b/test/tests/unit/vector_transfers/pull_lagrange_vector_nearest_location_transfer_master.i @@ -0,0 +1,78 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [received_vector] + family = LAGRANGE_VEC + order = FIRST + [] + + [expected_vector] + family = LAGRANGE_VEC + order = FIRST + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = expected_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'pull_lagrange_vector_nearest_location_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [pull] + type = MultiAppGeneralFieldNearestLocationTransfer + from_multi_app = sub_app + source_variable = sent_vector + variable = received_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = received_vector + other_variable = expected_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/pull_lagrange_vector_nearest_location_transfer_subapp.i b/test/tests/unit/vector_transfers/pull_lagrange_vector_nearest_location_transfer_subapp.i new file mode 100644 index 00000000..1da2065f --- /dev/null +++ b/test/tests/unit/vector_transfers/pull_lagrange_vector_nearest_location_transfer_subapp.i @@ -0,0 +1,58 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = LAGRANGE_VEC + order = FIRST + [] + + [sent_vector_x] + family = LAGRANGE + order = FIRST + [] + + [sent_vector_y] + family = LAGRANGE + order = FIRST + [] + + [sent_vector_z] + family = LAGRANGE + order = FIRST + [] +[] + + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] diff --git a/test/tests/unit/vector_transfers/pull_monomial_vector_nearest_location_transfer_master.i b/test/tests/unit/vector_transfers/pull_monomial_vector_nearest_location_transfer_master.i new file mode 100644 index 00000000..2d30e9b7 --- /dev/null +++ b/test/tests/unit/vector_transfers/pull_monomial_vector_nearest_location_transfer_master.i @@ -0,0 +1,78 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [received_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [expected_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = expected_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'pull_monomial_vector_nearest_location_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [pull] + type = MultiAppGeneralFieldNearestLocationTransfer + from_multi_app = sub_app + source_variable = sent_vector + variable = received_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = received_vector + other_variable = expected_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/pull_monomial_vector_nearest_location_transfer_subapp.i b/test/tests/unit/vector_transfers/pull_monomial_vector_nearest_location_transfer_subapp.i new file mode 100644 index 00000000..b8856d77 --- /dev/null +++ b/test/tests/unit/vector_transfers/pull_monomial_vector_nearest_location_transfer_subapp.i @@ -0,0 +1,58 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [sent_vector_x] + family = MONOMIAL + order = CONSTANT + [] + + [sent_vector_y] + family = MONOMIAL + order = CONSTANT + [] + + [sent_vector_z] + family = MONOMIAL + order = CONSTANT + [] +[] + + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] diff --git a/test/tests/unit/vector_transfers/push_lagrange_vector_nearest_location_transfer_master.i b/test/tests/unit/vector_transfers/push_lagrange_vector_nearest_location_transfer_master.i new file mode 100644 index 00000000..8fe42a58 --- /dev/null +++ b/test/tests/unit/vector_transfers/push_lagrange_vector_nearest_location_transfer_master.i @@ -0,0 +1,60 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = LAGRANGE_VEC + order = FIRST + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'push_lagrange_vector_nearest_location_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [push] + type = MultiAppGeneralFieldNearestLocationTransfer + to_multi_app = sub_app + source_variable = sent_vector + variable = received_vector_sub_app + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/push_lagrange_vector_nearest_location_transfer_subapp.i b/test/tests/unit/vector_transfers/push_lagrange_vector_nearest_location_transfer_subapp.i new file mode 100644 index 00000000..e5f26b7a --- /dev/null +++ b/test/tests/unit/vector_transfers/push_lagrange_vector_nearest_location_transfer_subapp.i @@ -0,0 +1,75 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [expected_vector] + family = LAGRANGE_VEC + order = FIRST + [] + + [received_vector_sub_app] + family = LAGRANGE_VEC + order = FIRST + [] + + [received_vector_sub_app_x] + family = LAGRANGE + order = FIRST + [] + + [received_vector_sub_app_y] + family = LAGRANGE + order = FIRST + [] + + [received_vector_sub_app_z] + family = LAGRANGE + order = FIRST + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = expected_vector + function = set_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = received_vector_sub_app + other_variable = expected_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] diff --git a/test/tests/unit/vector_transfers/push_monomial_vector_nearest_location_transfer_master.i b/test/tests/unit/vector_transfers/push_monomial_vector_nearest_location_transfer_master.i new file mode 100644 index 00000000..6b67dfe1 --- /dev/null +++ b/test/tests/unit/vector_transfers/push_monomial_vector_nearest_location_transfer_master.i @@ -0,0 +1,60 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'push_monomial_vector_nearest_location_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [push] + type = MultiAppGeneralFieldNearestLocationTransfer + to_multi_app = sub_app + source_variable = sent_vector + variable = received_vector_sub_app + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/push_monomial_vector_nearest_location_transfer_subapp.i b/test/tests/unit/vector_transfers/push_monomial_vector_nearest_location_transfer_subapp.i new file mode 100644 index 00000000..57c85fd6 --- /dev/null +++ b/test/tests/unit/vector_transfers/push_monomial_vector_nearest_location_transfer_subapp.i @@ -0,0 +1,75 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [expected_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [received_vector_sub_app] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [received_vector_sub_app_x] + family = MONOMIAL + order = CONSTANT + [] + + [received_vector_sub_app_y] + family = MONOMIAL + order = CONSTANT + [] + + [received_vector_sub_app_z] + family = MONOMIAL + order = CONSTANT + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = expected_vector + function = set_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = received_vector_sub_app + other_variable = expected_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] diff --git a/test/tests/unit/vector_transfers/push_pull_lagrange_vector_nearest_location_transfer_master.i b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_nearest_location_transfer_master.i new file mode 100644 index 00000000..b3f9f5f5 --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_nearest_location_transfer_master.i @@ -0,0 +1,85 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = LAGRANGE_VEC + order = FIRST + [] + + [received_vector] + family = LAGRANGE_VEC + order = FIRST + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'push_pull_lagrange_vector_nearest_location_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [push] + type = MultiAppGeneralFieldNearestLocationTransfer + to_multi_app = sub_app + source_variable = sent_vector + variable = received_vector_sub_app + [] + + [pull] + type = MultiAppGeneralFieldNearestLocationTransfer + from_multi_app = sub_app + source_variable = received_vector_sub_app + variable = received_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = sent_vector + other_variable = received_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/push_pull_lagrange_vector_nearest_location_transfer_subapp.i b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_nearest_location_transfer_subapp.i new file mode 100644 index 00000000..89ca98ad --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_nearest_location_transfer_subapp.i @@ -0,0 +1,40 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [received_vector_sub_app] + family = LAGRANGE_VEC + order = FIRST + [] + + [received_vector_sub_app_x] + family = LAGRANGE + order = FIRST + [] + + [received_vector_sub_app_y] + family = LAGRANGE + order = FIRST + [] + + [received_vector_sub_app_z] + family = LAGRANGE + order = FIRST + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] diff --git a/test/tests/unit/vector_transfers/push_pull_lagrange_vector_shape_evaluation_transfer_master.i b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_shape_evaluation_transfer_master.i new file mode 100644 index 00000000..fef19d08 --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_shape_evaluation_transfer_master.i @@ -0,0 +1,85 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = LAGRANGE_VEC + order = FIRST + [] + + [received_vector] + family = LAGRANGE_VEC + order = FIRST + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'push_pull_lagrange_vector_shape_evaluation_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [push] + type = MultiAppGeneralFieldShapeEvaluationTransfer + to_multi_app = sub_app + source_variable = sent_vector + variable = received_vector_sub_app + [] + + [pull] + type = MultiAppGeneralFieldShapeEvaluationTransfer + from_multi_app = sub_app + source_variable = received_vector_sub_app + variable = received_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = sent_vector + other_variable = received_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/push_pull_lagrange_vector_shape_evaluation_transfer_subapp.i b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_shape_evaluation_transfer_subapp.i new file mode 100644 index 00000000..89ca98ad --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_lagrange_vector_shape_evaluation_transfer_subapp.i @@ -0,0 +1,40 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [received_vector_sub_app] + family = LAGRANGE_VEC + order = FIRST + [] + + [received_vector_sub_app_x] + family = LAGRANGE + order = FIRST + [] + + [received_vector_sub_app_y] + family = LAGRANGE + order = FIRST + [] + + [received_vector_sub_app_z] + family = LAGRANGE + order = FIRST + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] diff --git a/test/tests/unit/vector_transfers/push_pull_monomial_vector_nearest_location_transfer_master.i b/test/tests/unit/vector_transfers/push_pull_monomial_vector_nearest_location_transfer_master.i new file mode 100644 index 00000000..911ed713 --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_monomial_vector_nearest_location_transfer_master.i @@ -0,0 +1,85 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [received_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'push_pull_monomial_vector_nearest_location_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [push] + type = MultiAppGeneralFieldNearestLocationTransfer + to_multi_app = sub_app + source_variable = sent_vector + variable = received_vector_sub_app + [] + + [pull] + type = MultiAppGeneralFieldNearestLocationTransfer + from_multi_app = sub_app + source_variable = received_vector_sub_app + variable = received_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = sent_vector + other_variable = received_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/push_pull_monomial_vector_nearest_location_transfer_subapp.i b/test/tests/unit/vector_transfers/push_pull_monomial_vector_nearest_location_transfer_subapp.i new file mode 100644 index 00000000..0ae23c3c --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_monomial_vector_nearest_location_transfer_subapp.i @@ -0,0 +1,40 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [received_vector_sub_app] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [received_vector_sub_app_x] + family = MONOMIAL + order = CONSTANT + [] + + [received_vector_sub_app_y] + family = MONOMIAL + order = CONSTANT + [] + + [received_vector_sub_app_z] + family = MONOMIAL + order = CONSTANT + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] diff --git a/test/tests/unit/vector_transfers/push_pull_monomial_vector_shape_evaluation_transfer_master.i b/test/tests/unit/vector_transfers/push_pull_monomial_vector_shape_evaluation_transfer_master.i new file mode 100644 index 00000000..2a9574ad --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_monomial_vector_shape_evaluation_transfer_master.i @@ -0,0 +1,85 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [sent_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [received_vector] + family = MONOMIAL_VEC + order = CONSTANT + [] +[] + +[Functions] + [set_vector] + type = ParsedVectorFunction + expression_x = '100*x*x' + expression_y = '100*y*y' + expression_z = '100*z*z' + [] +[] + +[ICs] + [set_vector] + type = VectorFunctionIC + variable = sent_vector + function = set_vector + [] +[] + +[MultiApps] + [sub_app] + type = TransientMultiApp + positions = '0 0 0' + input_files = 'push_pull_monomial_vector_shape_evaluation_transfer_subapp.i' + execute_on = timestep_begin + [] +[] + +[VectorTransfers] + [push] + type = MultiAppGeneralFieldShapeEvaluationTransfer + to_multi_app = sub_app + source_variable = sent_vector + variable = received_vector_sub_app + [] + + [pull] + type = MultiAppGeneralFieldShapeEvaluationTransfer + from_multi_app = sub_app + source_variable = received_vector_sub_app + variable = received_vector + [] +[] + +[Postprocessors] + [vector_l2_difference] + type = ElementVectorL2Difference + variable = sent_vector + other_variable = received_vector + execute_on = timestep_end + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] + +[Outputs] + csv = true +[] \ No newline at end of file diff --git a/test/tests/unit/vector_transfers/push_pull_monomial_vector_shape_evaluation_transfer_subapp.i b/test/tests/unit/vector_transfers/push_pull_monomial_vector_shape_evaluation_transfer_subapp.i new file mode 100644 index 00000000..0ae23c3c --- /dev/null +++ b/test/tests/unit/vector_transfers/push_pull_monomial_vector_shape_evaluation_transfer_subapp.i @@ -0,0 +1,40 @@ +[Mesh] + type = GeneratedMesh + dim = 3 + nx = 5 + ny = 5 + nz = 5 +[] + +[Problem] + solve = false +[] + +[AuxVariables] + [received_vector_sub_app] + family = MONOMIAL_VEC + order = CONSTANT + [] + + [received_vector_sub_app_x] + family = MONOMIAL + order = CONSTANT + [] + + [received_vector_sub_app_y] + family = MONOMIAL + order = CONSTANT + [] + + [received_vector_sub_app_z] + family = MONOMIAL + order = CONSTANT + [] +[] + +[Executioner] + type = Transient + dt = 1.0 + start_time = 0.0 + end_time = 1.0 +[] diff --git a/test/tests/unit/vector_transfers/tests b/test/tests/unit/vector_transfers/tests new file mode 100644 index 00000000..d0555795 --- /dev/null +++ b/test/tests/unit/vector_transfers/tests @@ -0,0 +1,59 @@ +[Tests] + design = 'syntax/Problem/index.md' + + [./PullLagrangeVectorNearestLocationTransfer] + type = 'CSVDiff' + input = 'pull_lagrange_vector_nearest_location_transfer_master.i' + csvdiff = 'pull_lagrange_vector_nearest_location_transfer_master_out.csv' + requirement = 'Apollo shall have the ability to pull a Lagrange vector from a subapp using the MultiAppGeneralFieldNearestLocationTransfer transfer.' + [] + + [./PushLagrangeVectorNearestLocationTransfer] + type = 'CSVDiff' + input = 'push_lagrange_vector_nearest_location_transfer_master.i' + csvdiff = 'push_lagrange_vector_nearest_location_transfer_master_out_sub_app0.csv' + requirement = 'Apollo shall have the ability to push a Lagrange vector to a subapp using the MultiAppGeneralFieldNearestLocationTransfer transfer.' + [] + + [./PushPullLagrangeVectorNearestLocationTransfer] + type = 'CSVDiff' + input = 'push_pull_lagrange_vector_nearest_location_transfer_master.i' + csvdiff = 'push_pull_lagrange_vector_nearest_location_transfer_master_out.csv' + requirement = 'Apollo shall have the ability to push and pull a Lagrange vector using the MultiAppGeneralFieldNearestLocationTransfer transfer.' + [] + + [./PushPullLagrangeVectorShapeEvaluationTransfer] + type = 'CSVDiff' + input = 'push_pull_lagrange_vector_shape_evaluation_transfer_master.i' + csvdiff = 'push_pull_lagrange_vector_shape_evaluation_transfer_master_out.csv' + requirement = 'Apollo shall have the ability to push and pull a Lagrange vector using the MultiAppShapeEvaluationTransfer transfer.' + [] + + [./PullMonomialVectorNearestLocationTransfer] + type = 'CSVDiff' + input = 'pull_monomial_vector_nearest_location_transfer_master.i' + csvdiff = 'pull_monomial_vector_nearest_location_transfer_master_out.csv' + requirement = 'Apollo shall have the ability to pull a Monomial vector from a subapp using the MultiAppGeneralFieldNearestLocationTransfer transfer.' + [] + + [./PushMonomialVectorNearestLocationTransfer] + type = 'CSVDiff' + input = 'push_monomial_vector_nearest_location_transfer_master.i' + csvdiff = 'push_monomial_vector_nearest_location_transfer_master_out_sub_app0.csv' + requirement = 'Apollo shall have the ability to push a Monomial vector to a subapp using the MultiAppGeneralFieldNearestLocationTransfer transfer.' + [] + + [./PushPullMonomialVectorNearestLocationTransfer] + type = 'CSVDiff' + input = 'push_pull_monomial_vector_nearest_location_transfer_master.i' + csvdiff = 'push_pull_monomial_vector_nearest_location_transfer_master_out.csv' + requirement = 'Apollo shall have the ability to push and pull a Monomial vector using the MultiAppGeneralFieldNearestLocationTransfer transfer.' + [] + + [./PushPullMonomialVectorShapeEvaluationTransfer] + type = 'CSVDiff' + input = 'push_pull_monomial_vector_shape_evaluation_transfer_master.i' + csvdiff = 'push_pull_monomial_vector_shape_evaluation_transfer_master_out.csv' + requirement = 'Apollo shall have the ability to push and pull a Monomial vector using the MultiAppShapeEvaluationTransfer transfer.' + [] +[]