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 SeparableScatterScalarResponse<PHAL::AlbanyTraits::Jacobian, Traits>::
evaluate2DFieldsDerivativesDueToExtrudedSolution(typename Traits::EvalData workset, std::string& sideset, Teuchos::RCP<const CellTopologyData> cellTopo)
{
  // Here we scatter the *local* response derivative
  Teuchos::RCP<Tpetra_MultiVector> dgdxT = workset.overlapped_dgdxT;
  Teuchos::RCP<Tpetra_MultiVector> dgdxdotT = workset.overlapped_dgdxdotT;
  Teuchos::RCP<Tpetra_MultiVector> dgT;
  if (dgdxT != Teuchos::null)
    dgT = dgdxT;
  else
    dgT = dgdxdotT;

  const int neq = workset.wsElNodeEqID[0][0].size();
  const Albany::NodalDOFManager& solDOFManager = workset.disc->getOverlapDOFManager("ordinary_solution");
  const Albany::LayeredMeshNumbering<LO>& layeredMeshNumbering = *workset.disc->getLayeredMeshNumbering();
  int numLayers = layeredMeshNumbering.numLayers;
  const Teuchos::ArrayRCP<Teuchos::ArrayRCP<GO> >& wsElNodeID  = workset.disc->getWsElNodeID()[workset.wsIndex];

  if (workset.sideSets == Teuchos::null)
      TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "Side sets not properly specified on the mesh" << std::endl);

  const Albany::SideSetList& ssList = *(workset.sideSets);
  Albany::SideSetList::const_iterator it = ssList.find(sideset);

  if (it != ssList.end()) {
    const std::vector<Albany::SideStruct>& sideSet = it->second;

    for (std::size_t iSide = 0; iSide < sideSet.size(); ++iSide) { // loop over the sides on this ws and name
      // Get the data that corresponds to the side
      const int elem_GID = sideSet[iSide].elem_GID;
      const int elem_LID = sideSet[iSide].elem_LID;
      const int elem_side = sideSet[iSide].side_local_id;
      const CellTopologyData_Subcell& side =  cellTopo->side[elem_side];
      int numSideNodes = side.topology->node_count;

      const Teuchos::ArrayRCP<GO>& elNodeID = wsElNodeID[elem_LID];
      for (std::size_t res = 0; res < this->global_response.size(); res++) {
        typename PHAL::Ref<ScalarT>::type val = this->local_response(elem_LID, res);
        LO base_id, ilayer;
        for (int i = 0; i < numSideNodes; ++i) {
          std::size_t node = side.node[i];
          LO lnodeId = workset.disc->getOverlapNodeMapT()->getLocalElement(elNodeID[node]);
          layeredMeshNumbering.getIndices(lnodeId, base_id, ilayer);
          for (unsigned int il_col=0; il_col<numLayers+1; il_col++) {
            LO inode = layeredMeshNumbering.getId(base_id, il_col);
            for (unsigned int eq_col=0; eq_col<neq; eq_col++) {
              LO dof = solDOFManager.getLocalDOF(inode, eq_col);
              int deriv = neq *this->numNodes+il_col*neq*numSideNodes + neq*i + eq_col;
              dgT->sumIntoLocalValue(dof, res, val.dx(deriv));
            }
          }
        }
      }
    }
  }
}
void SeparableScatterScalarResponse<PHAL::AlbanyTraits::MPJacobian, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  // Here we scatter the *local* MP response derivative
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dgdx_mp =
    workset.overlapped_mp_dgdx;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dgdxdot_mp =
    workset.overlapped_mp_dgdxdot;
  Teuchos::RCP<Stokhos::ProductEpetraMultiVector> dg_mp;
  if (dgdx_mp != Teuchos::null)
    dg_mp = dgdx_mp;
  else
    dg_mp = dgdxdot_mp;

  // Loop over cells in workset
  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID =
      workset.wsElNodeEqID[cell];

    // Loop over responses
    for (std::size_t res = 0; res < this->global_response.size(); res++) {
      typename PHAL::Ref<ScalarT>::type val = this->local_response(cell, res);

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

        // Loop over equations per node
        for (unsigned 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++)
            (*dg_mp)[block].SumIntoMyValue(dof, res,
                                           val.dx(deriv).coeff(block));

        } // column equations
      } // response
    } // node
  } // cell
}
void SeparableScatterScalarResponse<PHAL::AlbanyTraits::Jacobian, Traits>::
evaluateFields(typename Traits::EvalData workset)
{
  // Here we scatter the *local* response derivative
  Teuchos::RCP<Tpetra_MultiVector> dgdxT = workset.overlapped_dgdxT;
  Teuchos::RCP<Tpetra_MultiVector> dgdxdotT = workset.overlapped_dgdxdotT;
  Teuchos::RCP<Tpetra_MultiVector> dgT;
  if (dgdxT != Teuchos::null)
    dgT = dgdxT;
  else
    dgT = dgdxdotT;

  // Loop over cells in workset
  for (std::size_t cell=0; cell < workset.numCells; ++cell) {
    const Teuchos::ArrayRCP<Teuchos::ArrayRCP<int> >& nodeID =
      workset.wsElNodeEqID[cell];

    // Loop over responses

    for (std::size_t res = 0; res < this->global_response.size(); res++) {
      typename PHAL::Ref<ScalarT>::type val = this->local_response(cell, res);

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

        // Loop over equations per node
        for (unsigned 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
          dgT->sumIntoLocalValue(dof, res, val.dx(deriv));

        } // column equations
      } // column nodes
    } // response

  } // cell
}
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);
}