void
PolycrystalElasticDrivingForceAction::act()
{
  #ifdef DEBUG
    Moose::err << "Inside the PolycrystalElasticDrivingForceAction Object\n";
    Moose::err << "var name base:" << _var_name_base;
  #endif

  for (unsigned int op = 0; op < _op_num; ++op)
  {
    // Create variable name
    std::string var_name = _var_name_base + Moose::stringify(op);

    // Create Stiffness derivative name
    MaterialPropertyName D_stiff_name = propertyNameFirst(_elasticity_tensor_name, var_name);

    //Set name of kernel being created
    std::string kernel_type = "ACGrGrElasticDrivingForce";

    // Set the actual parameters for the kernel
    InputParameters poly_params = _factory.getValidParams(kernel_type);
    poly_params.set<NonlinearVariableName>("variable") = var_name;
    poly_params.set<MaterialPropertyName>("D_tensor_name") = D_stiff_name;
    poly_params.set<bool>("use_displaced_mesh") = getParam<bool>("use_displaced_mesh");

    std::string kernel_name = "AC_ElasticDrivingForce_" + var_name;

    // Create kernel
    _problem->addKernel(kernel_type, kernel_name, poly_params);
  }
}
ComputeExternalGrainForceAndTorque::ComputeExternalGrainForceAndTorque(const InputParameters & parameters) :
    DerivativeMaterialInterface<ShapeElementUserObject>(parameters),
    GrainForceAndTorqueInterface(),
    _c_name(getVar("c", 0)->name()),
    _c_var(coupled("c")),
    _dF_name(getParam<MaterialPropertyName>("force_density")),
    _dF(getMaterialPropertyByName<std::vector<RealGradient> >(_dF_name)),
    _dFdc(getMaterialPropertyByName<std::vector<RealGradient> >(propertyNameFirst(_dF_name, _c_name))),
    _op_num(coupledComponents("etas")),
    _grain_tracker(getUserObject<GrainTrackerInterface>("grain_data")),
    _vals_var(_op_num),
    _vals_name(_op_num),
    _dFdeta(_op_num)
{
  for (unsigned int i = 0; i < _op_num; ++i)
  {
    _vals_var[i] = coupled("etas", i);
    _vals_name[i] = getVar("etas", i)->name();
    _dFdeta[i] = &getMaterialPropertyByName<std::vector<RealGradient> >(propertyNameFirst(_dF_name, _vals_name[i]));
  }
}
ComputePolycrystalElasticityTensor::ComputePolycrystalElasticityTensor(const InputParameters & parameters) :
    ComputeElasticityTensorBase(parameters),
    _C_unrotated(getParam<std::vector<Real> >("Elastic_constants"), (RankFourTensor::FillMethod)(int)getParam<MooseEnum>("fill_method")), // TODO: rename to lower case "elastic_constants"
    _length_scale(getParam<Real>("length_scale")),
    _pressure_scale(getParam<Real>("pressure_scale")),
    _euler(getUserObject<EulerAngleProvider>("euler_angle_provider")),
    _grain_tracker(getUserObject<GrainTracker>("GrainTracker_object")), // TODO: Rename to lower case "grain_tracker"
    _grain_num(getParam<unsigned int>("grain_num")),
    _nop(coupledComponents("v")),
    _stiffness_buffer(getParam<unsigned int>("stiffness_buffer")),
    _vals(_nop),
    _D_elastic_tensor(_nop),
    _C_rotated(_grain_num + _stiffness_buffer),
    _JtoeV(6.24150974e18) // Joule to eV conversion
{
  // Read in Euler angles from the Euler angle provider
  if (_euler.getGrainNum() < _grain_num)
    mooseError("Euler angle provider has too few angles.");

  // Loop over grains
  for (unsigned int grn = 0; grn < _grain_num; ++grn)
  {
    // Rotate one elasticity tensor for each grain
    RotationTensor R(_euler.getEulerAngles(grn));
    _C_rotated[grn] = _C_unrotated;
    _C_rotated[grn].rotate(R);

    if (grn < _stiffness_buffer)
    {
      _C_rotated[grn + _grain_num] = _C_unrotated;
      _C_rotated[grn + _grain_num].rotate(R);
    }
  }

  // Loop over variables (ops)
  for (unsigned int op = 0; op < _nop; ++op)
  {
    // Initialize variables
    _vals[op] = &coupledValue("v", op);

    // Create variable name
    std::string var_name = getParam<std::string>("var_name_base") + Moose::stringify(op);

    // Create names of derivative properties of elasticity tensor
    std::string material_name = propertyNameFirst(_elasticity_tensor_name, var_name);

    // declare elasticity tensor derivative properties
    _D_elastic_tensor[op] = &declareProperty<RankFourTensor>(material_name);
  }
}
void
DerivativeFunctionMaterialBase::initialSetup()
{
  // set the _prop_* pointers of all material properties that are not beeing used back to NULL
  unsigned int i, j, k;
  bool needs_third_derivatives = false;

  if (!_fe_problem.isMatPropRequested(_F_name))
    _prop_F = NULL;

  for (i = 0; i < _nargs; ++i)
  {
    if (!_fe_problem.isMatPropRequested(propertyNameFirst(_F_name, _arg_names[i])))
      _prop_dF[i] = NULL;

    // second derivatives
    for (j = i; j < _nargs; ++j)
    {
      if (!_fe_problem.isMatPropRequested(propertyNameSecond(_F_name, _arg_names[i], _arg_names[j])))
        _prop_d2F[i][j] =
        _prop_d2F[j][i] = NULL;

      // third derivatives
      if (_third_derivatives)
      {
        for (k = j; k < _nargs; ++k)
        {
          if (!_fe_problem.isMatPropRequested(propertyNameThird(_F_name, _arg_names[i], _arg_names[j], _arg_names[k])))
            _prop_d3F[i][j][k] =
            _prop_d3F[k][i][j] =
            _prop_d3F[j][k][i] =
            _prop_d3F[k][j][i] =
            _prop_d3F[j][i][k] =
            _prop_d3F[i][k][j] = NULL;
          else
            needs_third_derivatives = true;
        }

        if (!needs_third_derivatives)
          mooseWarning("This simulation does not actually need the third derivatives of DerivativeFunctionMaterialBase " + _name);
      }
    }
  }
}
ComputeGrainForceAndTorque::ComputeGrainForceAndTorque(const InputParameters & parameters) :
    ElementUserObject(parameters),
    GrainForceAndTorqueInterface(),
    _c_name(getVar("c", 0)->name()),
    _dF(getMaterialProperty<std::vector<RealGradient> >("force_density")),
    _dF_name(getParam<MaterialPropertyName>("force_density")),
    _dFdc(getMaterialPropertyByName<std::vector<RealGradient> >(propertyNameFirst(_dF_name, _c_name))),
    _grain_data(getUserObject<ComputeGrainCenterUserObject>("grain_data")),
    _grain_volumes(_grain_data.getGrainVolumes()),
    _grain_centers(_grain_data.getGrainCenters()),
    _ncrys(_grain_volumes.size()),
    _ncomp(6*_ncrys),
    _force_values(_ncrys),
    _torque_values(_ncrys),
    _force_derivatives(_ncrys),
    _torque_derivatives(_ncrys),
    _force_torque_store(_ncomp),
    _force_torque_derivative_store(_ncomp)
{
}
void
ComputeVolumetricEigenstrain::initialSetup()
{
  for (auto vmn : _volumetric_material_names)
    validateCoupling<Real>(vmn);

  for (unsigned int i = 0; i < _num_args; ++i)
  {
    const VariableName & iname = getVar("args", i)->name();
    if (_fe_problem.isMatPropRequested(propertyNameFirst(_base_name + "elastic_strain", iname)))
      mooseError("Derivative of elastic_strain requested, but not yet implemented");
    else
      _delastic_strain[i] = nullptr;
    for (unsigned int j = 0; j < _num_args; ++j)
    {
      const VariableName & jname = getVar("args", j)->name();
      if (_fe_problem.isMatPropRequested(
              propertyNameSecond(_base_name + "elastic_strain", iname, jname)))
        mooseError("Second Derivative of elastic_strain requested, but not yet implemented");
      else
        _d2elastic_strain[i][j] = nullptr;
    }
  }
}
ComputePolycrystalElasticityTensor::ComputePolycrystalElasticityTensor(const InputParameters & parameters) :
    ComputeElasticityTensorBase(parameters),
    _C_unrotated(getParam<std::vector<Real> >("Elastic_constants"), (RankFourTensor::FillMethod)(int)getParam<MooseEnum>("fill_method")),
    _length_scale(getParam<Real>("length_scale")),
    _pressure_scale(getParam<Real>("pressure_scale")),
    _Euler_angles_file_name(getParam<FileName>("Euler_angles_file_name")),
    _grain_tracker(getUserObject<GrainTracker>("GrainTracker_object")),
    _grain_num(getParam<unsigned int>("grain_num")),
    _stiffness_buffer(getParam<unsigned int>("stiffness_buffer")),
    _JtoeV(6.24150974e18), // Joule to eV conversion
    _nop(coupledComponents("v"))
{
  // Initialize values for crystals
  _vals.resize(_nop);
  _D_elastic_tensor.resize(_nop);
  _C_rotated.resize(_grain_num + _stiffness_buffer);

  // Read in Euler angles from "angle_file_name"
  std::ifstream inFile(_Euler_angles_file_name.c_str());

  if (!inFile)
    mooseError("Can't open " + _Euler_angles_file_name);

  for (unsigned int i = 0; i < 4; ++i)
    inFile.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // ignore line

  Real weight;

  // Loop over grains
  for (unsigned int grn = 0; grn < _grain_num; ++grn)
  {
    // Read in Euler angles
    RealVectorValue Euler_Angles;
    for (unsigned int j=0; j<3; ++j)
      inFile >> Euler_Angles(j);

    // Read in weight
    inFile >> weight;

    // Rotate one elasticity tensor for each grain
    RotationTensor R(Euler_Angles);
    _C_rotated[grn] = _C_unrotated;
    _C_rotated[grn].rotate(R);

    if (grn < _stiffness_buffer)
    {
      _C_rotated[grn + _grain_num] = _C_unrotated;
      _C_rotated[grn + _grain_num].rotate(R);
    }
  }

  // Close Euler angle file
  inFile.close();

  // Loop over variables (ops)
  for (unsigned int op = 0; op < _nop; ++op)
  {
    // Initialize variables
    _vals[op] = &coupledValue("v", op);

    // Create variable name
    std::string var_name = getParam<std::string>("var_name_base") + Moose::stringify(op);

    // Create names of derivative properties of elasticity tensor
    std::string material_name = propertyNameFirst(_elasticity_tensor_name, var_name);

    // declare elasticity tensor derivative properties
    _D_elastic_tensor[op] = &declareProperty<ElasticityTensorR4>(material_name);
  }
}