Skip to content

Commit

Permalink
Add coupling validation routines (idaholab#5595)
Browse files Browse the repository at this point in the history
  • Loading branch information
dschwen committed Aug 28, 2015
1 parent a21b6bf commit 4a11efa
Show file tree
Hide file tree
Showing 2 changed files with 122 additions and 0 deletions.
114 changes: 114 additions & 0 deletions framework/include/materials/DerivativeMaterialInterface.h
Expand Up @@ -16,6 +16,7 @@

#include "Material.h"
#include "MaterialProperty.h"
#include "KernelBase.h"
#include "FEProblem.h"
#include "BlockRestrictable.h"
#include "BoundaryRestrictable.h"
Expand Down Expand Up @@ -104,6 +105,17 @@ class DerivativeMaterialInterface :
const MaterialProperty<U> & getMaterialPropertyDerivativeByName(const MaterialPropertyName & base, const VariableName & c1, const VariableName & c2 = "", const VariableName & c3 = "");
///@}

///@{
/**
* check if derivatives of the passed in material property exist w.r.t a variable
* that is _not_ coupled in to the current object
*/
template<typename U>
void validateCoupling(const MaterialPropertyName & base, const std::vector<VariableName> & c);
template<typename U>
void validateCoupling(const MaterialPropertyName & base, const VariableName & c1, const VariableName & c2 = "", const VariableName & c3 = "");
///@}

private:
/// Return a constant zero property
template<typename U>
Expand All @@ -113,6 +125,13 @@ class DerivativeMaterialInterface :
template<typename U>
bool haveMaterialProperty(const std::string & prop_name);

/// helper method to compile list of missing coupled variables for a given system
template<typename U>
void validateCouplingHelper(const MaterialPropertyName & base, const std::vector<VariableName> & c, const System & system, std::vector<VariableName> & missing);

// check if the speciified variable name is not the variable this kernel is acting on (always true for any other type of object)
bool isNotKernelVariable(const VariableName & name);

/// Reference to FEProblem
FEProblem & _dmi_fe_problem;

Expand Down Expand Up @@ -305,4 +324,99 @@ DerivativeMaterialInterface<T>::getMaterialPropertyDerivativeByName(const Materi
return getDefaultMaterialPropertyByName<U>(propertyNameFirst(base, c1));
}

template<class T>
template<typename U>
void
DerivativeMaterialInterface<T>::validateCouplingHelper(const MaterialPropertyName & base, const std::vector<VariableName> & c, const System & system, std::vector<VariableName> & missing)
{
unsigned int ncoupled = this->_coupled_moose_vars.size();

// iterate over all variables in the current system (in groups)
for (unsigned int i = 0; i < system.n_variable_groups(); ++i)
{
const VariableGroup & vg = system.variable_group(i);
for (unsigned int j = 0; j < vg.n_variables(); ++j)
{
std::vector<VariableName> cj(c);
VariableName jname = vg.name(j);
cj.push_back(jname);

// if the derivative exists make sure the variable is coupled
if (haveMaterialProperty<U>(propertyName(base, cj)))
{
// kernels to not have the variable they are acting on in coupled_moose_vars
bool is_missing = isNotKernelVariable(jname);

for (unsigned int k = 0; k < ncoupled; ++k)
if (this->_coupled_moose_vars[j]->name() == jname)
{
is_missing = false;
break;
}

if (is_missing)
missing.push_back(jname);
}
}
}
}

template<class T>
template<typename U>
void
DerivativeMaterialInterface<T>::validateCoupling(const MaterialPropertyName & base, const std::vector<VariableName> & c)
{
// get the base property name
std::string prop_name = this->deducePropertyName(base);
// list of potentially missing coupled variables
std::vector<VariableName> missing;

// iterate over all variables in the both the non-linear and auxiliary system
validateCouplingHelper<U>(prop_name, c, _dmi_fe_problem.getAuxiliarySystem().system(), missing);
validateCouplingHelper<U>(prop_name, c, _dmi_fe_problem.getNonlinearSystem().system(), missing);

if (missing.size() > 0)
{
// join list of missing variable names
std::string list = missing[0];
for (unsigned int i = 1; i < missing.size(); ++i)
list += ", " + missing[i];

mooseError("Missing coupled variables {" << list << "} (add them to args)");
}
}

template<class T>
template<typename U>
void
DerivativeMaterialInterface<T>::validateCoupling(const MaterialPropertyName & base, const VariableName & c1, const VariableName & c2, const VariableName & c3)
{
std::vector<VariableName> c(1, c1);
if (c2 != "")
{
c.push_back(c2);
if (c3 != "")
c.push_back(c3);
}
validateCoupling<U>(base, c);
}

template<class T>
inline bool
DerivativeMaterialInterface<T>::isNotKernelVariable(const VariableName & name)
{
// try to cast this to a Kernel pointer
KernelBase * k = dynamic_cast<KernelBase *>(this);

// This interface is not templated on a class derived from Kernel
if (k == NULL)
{
mooseWarning("this is not a Kernel");
return true;
}

// We are templated on a kernel class, so we check if the kernel variable
return k->variable().name() != name;
}

#endif //DERIVATIVEMATERIALINTERFACE_H
8 changes: 8 additions & 0 deletions modules/phase_field/include/kernels/CahnHilliardBase.h
Expand Up @@ -21,6 +21,7 @@ class CahnHilliardBase : public CHBulk<T>
CahnHilliardBase(const InputParameters & parameters);

static InputParameters validParams();
virtual void initialSetup();

protected:
typedef typename CHBulk<T>::PFFunctionType PFFunctionType;
Expand Down Expand Up @@ -77,6 +78,13 @@ CahnHilliardBase<T>::CahnHilliardBase(const InputParameters & parameters) :
}
}

template<typename T>
void
CahnHilliardBase<T>:: initialSetup()
{
this->template validateCoupling<Real>("f_name", this->_var.name());
}

template<typename T>
RealGradient
CahnHilliardBase<T>::computeGradDFDCons(PFFunctionType type)
Expand Down

0 comments on commit 4a11efa

Please sign in to comment.