void SeparableScatterScalarResponse<PHAL::AlbanyTraits::MPJacobian, Traits>::
postEvaluate(typename Traits::PostEvalData workset)
{
  // Here we scatter the *global* MP response
  Teuchos::RCP<Stokhos::ProductEpetraVector> g_mp = workset.mp_g;
  if (g_mp != Teuchos::null) {
    for (std::size_t res = 0; res < this->global_response.size(); res++) {
      typename PHAL::Ref<ScalarT>::type val = this->global_response[res];
      for (int block=0; block<g_mp->size(); block++)
        (*g_mp)[block][res] = val.val().coeff(block);
    }
  }

  // Here we scatter the *global* MP response derivatives
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dgdx_mp =
    workset.mp_dgdx;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> overlapped_dgdx_mp =
    workset.overlapped_mp_dgdx;
  if (dgdx_mp != Teuchos::null)
    for (int block=0; block<dgdx_mp->size(); block++)
      (*dgdx_mp)[block].Export((*overlapped_dgdx_mp)[block],
                               *workset.x_importer, Add);

  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dgdxdot_mp =
    workset.mp_dgdxdot;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> overlapped_dgdxdot_mp =
    workset.overlapped_mp_dgdxdot;
  if (dgdxdot_mp != Teuchos::null)
    for (int block=0; block<dgdxdot_mp->size(); block++)
      (*dgdxdot_mp)[block].Export((*overlapped_dgdxdot_mp)[block],
                                  *workset.x_importer, Add);
}
void FastSolutionTensorInterpolationBase<PHAL::AlbanyTraits::Jacobian, Traits, typename PHAL::AlbanyTraits::Jacobian::ScalarT>::
evaluateFields(typename Traits::EvalData workset)
{
  const int num_dof = this->val_node(0,0,0,0).size();
  const int neq = workset.wsElNodeEqID.dimension(2);
  const auto vecDim = this->vecDim;
  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    for (std::size_t qp=0; qp < this->numQPs; ++qp) {
      for (std::size_t i=0; i< vecDim; i++) {
        for (std::size_t j=0; j< vecDim; j++) {
          // Zero out for node==0; then += for node = 1 to numNodes
          typename PHAL::Ref<ScalarT>::type vqp = this->val_qp(cell,qp,i,j);

          vqp = this->val_node(cell, 0, i, j) * this->BF(cell, 0, qp);
          vqp = ScalarT(num_dof, this->val_node(cell, 0, i, j).val() * this->BF(cell, 0, qp));
          vqp.fastAccessDx(offset+i*vecDim+j) = this->val_node(cell, 0, i, j).fastAccessDx(offset+i*vecDim+j) * this->BF(cell, 0, qp);
          for (std::size_t node=1; node < this->numNodes; ++node) {
            vqp.val() += this->val_node(cell, node, i, j).val() * this->BF(cell, node, qp);
            vqp.fastAccessDx(neq*node+offset+i*this->vecDim+j)
              += this->val_node(cell, node, i, j).fastAccessDx(neq*node+offset+i*vecDim+j) * this->BF(cell, node, qp);
          }
        }
      }
    }
  }
}
void ScatterScalarResponse<PHAL::AlbanyTraits::Tangent, Traits>::
postEvaluate(typename Traits::PostEvalData workset)
{
  // Here we scatter the *global* response and tangent
  //Teuchos::RCP<Epetra_Vector> g = workset.g;
  //Teuchos::RCP<Epetra_MultiVector> gx = workset.dgdx;
  //Teuchos::RCP<Epetra_MultiVector> gp = workset.dgdp;
  Teuchos::RCP<Tpetra_Vector> gT = workset.gT;
  Teuchos::RCP<Tpetra_MultiVector> gxT = workset.dgdxT;
  Teuchos::RCP<Tpetra_MultiVector> gpT = workset.dgdpT;
  for (PHAL::MDFieldIterator<ScalarT> gr(this->global_response);
       ! gr.done(); ++gr) {
    typename PHAL::Ref<ScalarT>::type val = *gr;
    const int res = gr.idx();
    if (gT != Teuchos::null){
      Teuchos::ArrayRCP<ST> gT_nonconstView = gT->get1dViewNonConst();
      gT_nonconstView[res] = val.val();
    }
    if (gxT != Teuchos::null)
      for (int col=0; col<workset.num_cols_x; col++)
	gxT->replaceLocalValue(res, col, val.dx(col));
    if (gpT != Teuchos::null)
      for (int col=0; col<workset.num_cols_p; col++)
	gpT->replaceLocalValue(res, col, val.dx(col+workset.param_offset));
  }
}
void ATO::TensorPNormResponseSpec<PHAL::AlbanyTraits::MPJacobian, Traits>::
postEvaluate(typename Traits::PostEvalData workset)
{
  this->global_response[0] = pow(this->global_response[0],1.0/pVal);

  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> overlapped_dgdx_mp = workset.overlapped_mp_dgdx;
  if(overlapped_dgdx_mp != Teuchos::null){
    for(int block=0; block<overlapped_dgdx_mp->size(); block++){
      typename PHAL::Ref<ScalarT>::type gVal = this->global_response[0];
      double scale = pow(gVal.val().coeff(block),1.0/pVal-1.0)/pVal;
      (*overlapped_dgdx_mp)[block].Scale(scale);
    }
  }

  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> overlapped_dgdxdot_mp = workset.overlapped_mp_dgdxdot;
  if(overlapped_dgdxdot_mp != Teuchos::null){
    for(int block=0; block<overlapped_dgdxdot_mp->size(); block++){
      typename PHAL::Ref<ScalarT>::type gVal = this->global_response[0];
      double scale = pow(gVal.val().coeff(block),1.0/pVal-1.0)/pVal;
      (*overlapped_dgdxdot_mp)[block].Scale(scale);
    }
  }
}
void
QCAD::FieldValueScatterScalarResponse<PHAL::AlbanyTraits::MPJacobian, Traits>::
postEvaluate(typename Traits::PostEvalData workset)
{
  // Here we scatter the *global* MP response
  Teuchos::RCP<Stokhos::ProductEpetraVector> g_mp = workset.mp_g;
  if (g_mp != Teuchos::null) {
    for (int res = 0; res < this->field_components.size(); res++) {
      typename PHAL::Ref<ScalarT>::type val = this->global_response(this->field_components[res]);
      for (int block=0; block<g_mp->size(); block++)
        (*g_mp)[block][res] = val.val().coeff(block);
    }
  }

  // Here we scatter the *global* MP response derivatives
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dgdx_mp =
    workset.mp_dgdx;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dgdxdot_mp =
    workset.mp_dgdxdot;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> overlapped_dgdx_mp =
    workset.overlapped_mp_dgdx;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> overlapped_dgdxdot_mp =
    workset.overlapped_mp_dgdxdot;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dg_mp, overlapped_dg_mp;
  if (dgdx_mp != Teuchos::null) {
    dg_mp = dgdx_mp;
    overlapped_dg_mp = overlapped_dgdx_mp;
  }
  else {
    dg_mp = dgdxdot_mp;
    overlapped_dg_mp = overlapped_dgdxdot_mp;
  }

  dg_mp->init(0.0);
  overlapped_dg_mp->init(0.0);

  // Extract derivatives for the cell corresponding to nodeID
  if (nodeID != Teuchos::null) {

    // Loop over responses
    for (int res = 0; res < this->field_components.size(); res++) {
      typename PHAL::Ref<ScalarT>::type val = this->global_response(this->field_components[res]);

      // Loop over nodes in cell
      for (int node_dof=0; node_dof<numNodes; node_dof++) {
        int neq = nodeID[node_dof].size();

        // Loop over equations per node
        for (int eq_dof=0; eq_dof<neq; eq_dof++) {

          // local derivative component
          int deriv = neq * node_dof + eq_dof;

          // local DOF
          int dof = nodeID[node_dof][eq_dof];

          // Set dg/dx
          for (int block=0; block<dg_mp->size(); block++)
            (*overlapped_dg_mp)[block].ReplaceMyValue(dof, res,
                                                      val.dx(deriv).coeff(block));

        } // column equations
      } // response
    } // node
  } // cell belongs to this proc

  for (int block=0; block<dgdx_mp->size(); block++)
    (*dg_mp)[block].Export((*overlapped_dg_mp)[block],
                           *workset.x_importer, Add);
}