Panzer  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Panzer_ScatterResidual_BlockedEpetra_impl.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Panzer: A partial differential equation assembly
5 // engine for strongly coupled complex multiphysics systems
6 // Copyright (2011) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Roger P. Pawlowski (rppawlo@sandia.gov) and
39 // Eric C. Cyr (eccyr@sandia.gov)
40 // ***********************************************************************
41 // @HEADER
42 
43 #ifndef PANZER_SCATTER_RESIDUAL_BLOCKEDEPETRA_IMPL_HPP
44 #define PANZER_SCATTER_RESIDUAL_BLOCKEDEPETRA_IMPL_HPP
45 
46 #include "Teuchos_RCP.hpp"
47 #include "Teuchos_Assert.hpp"
48 
49 #include "Phalanx_DataLayout.hpp"
50 
51 #include "Epetra_Map.h"
52 #include "Epetra_Vector.h"
53 #include "Epetra_CrsMatrix.h"
54 
55 #include "Panzer_GlobalIndexer.hpp"
57 #include "Panzer_PureBasis.hpp"
60 #include "Panzer_HashUtils.hpp"
62 
63 #include "Thyra_SpmdVectorBase.hpp"
64 #include "Thyra_ProductVectorBase.hpp"
65 #include "Thyra_DefaultProductVector.hpp"
66 #include "Thyra_BlockedLinearOpBase.hpp"
67 #include "Thyra_DefaultBlockedLinearOp.hpp"
68 #include "Thyra_get_Epetra_Operator.hpp"
69 
70 #include "Phalanx_DataLayout_MDALayout.hpp"
71 
72 #include "Teuchos_FancyOStream.hpp"
73 
74 // **********************************************************************
75 // Specialization: Residual
76 // **********************************************************************
77 
78 template<typename TRAITS,typename LO,typename GO>
81  const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
82  const Teuchos::ParameterList& p,
83  bool /* useDiscreteAdjoint */)
84  : rowIndexers_(rIndexers)
85  , colIndexers_(cIndexers)
86  , globalDataKey_("Residual Scatter Container")
87 {
88  std::string scatterName = p.get<std::string>("Scatter Name");
89  scatterHolder_ =
90  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
91 
92  // get names to be evaluated
93  const std::vector<std::string>& names =
94  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
95 
96  // grab map from evaluated names to field names
97  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
98 
100  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
101 
102  // build the vector of fields that this is dependent on
103  scatterFields_.resize(names.size());
104  for (std::size_t eq = 0; eq < names.size(); ++eq) {
105  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
106 
107  // tell the field manager that we depend on this field
108  this->addDependentField(scatterFields_[eq]);
109  }
110 
111  // this is what this evaluator provides
112  this->addEvaluatedField(*scatterHolder_);
113 
114  if (p.isType<std::string>("Global Data Key"))
115  globalDataKey_ = p.get<std::string>("Global Data Key");
116 
117  this->setName(scatterName+" Scatter Residual");
118 }
119 
120 // **********************************************************************
121 template<typename TRAITS,typename LO,typename GO>
123 postRegistrationSetup(typename TRAITS::SetupData /* d */,
124  PHX::FieldManager<TRAITS>& /* fm */)
125 {
126  indexerIds_.resize(scatterFields_.size());
127  subFieldIds_.resize(scatterFields_.size());
128 
129  // load required field numbers for fast use
130  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
131  // get field ID from DOF manager
132  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
133 
134  indexerIds_[fd] = getFieldBlock(fieldName,rowIndexers_);
135  subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
136  }
137 }
138 
139 // **********************************************************************
140 template<typename TRAITS,typename LO,typename GO>
142 preEvaluate(typename TRAITS::PreEvalData d)
143 {
144  typedef BlockedEpetraLinearObjContainer BLOC;
145  typedef BlockedEpetraLinearObjContainer ELOC;
146 
147  // extract linear object container
148  Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<const BLOC>(d.gedc->getDataObject(globalDataKey_));
149  Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<const ELOC>(d.gedc->getDataObject(globalDataKey_));
150 
151  // if its blocked do this
152  if(blockedContainer!=Teuchos::null)
153  r_ = Teuchos::rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(blockedContainer->get_f());
154  else if(epetraContainer!=Teuchos::null) // if its straight up epetra do this
155  r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
156 
157  TEUCHOS_ASSERT(r_!=Teuchos::null);
158 }
159 
160 // **********************************************************************
161 template<typename TRAITS,typename LO,typename GO>
163 evaluateFields(typename TRAITS::EvalData workset)
164 {
165  using Teuchos::RCP;
166  using Teuchos::ptrFromRef;
167  using Teuchos::rcp_dynamic_cast;
168 
169  using Thyra::VectorBase;
170  using Thyra::SpmdVectorBase;
172 
173  // for convenience pull out some objects from workset
174  std::string blockId = this->wda(workset).block_id;
175  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
176 
177  // NOTE: A reordering of these loops will likely improve performance
178  // The "getGIDFieldOffsets may be expensive. However the
179  // "getElementGIDs" can be cheaper. However the lookup for LIDs
180  // may be more expensive!
181 
182  // loop over each field to be scattered
184  for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
185  int indexerId = indexerIds_[fieldIndex];
186  int subFieldNum = subFieldIds_[fieldIndex];
187 
188  // grab local data for inputing
189  rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(indexerId))->getNonconstLocalData(ptrFromRef(local_r));
190 
191  auto subRowIndexer = rowIndexers_[indexerId];
192  const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
193 
194  // scatter operation for each cell in workset
195  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
196  std::size_t cellLocalId = localCellIds[worksetCellIndex];
197 
198  auto LIDs = subRowIndexer->getElementLIDs(cellLocalId);
199 
200  // loop over basis functions
201  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
202  int offset = elmtOffset[basis];
203  int lid = LIDs[offset];
204  local_r[lid] += (scatterFields_[fieldIndex])(worksetCellIndex,basis);
205  }
206  }
207  }
208 }
209 
210 // **********************************************************************
211 // Specialization: Tangent
212 // **********************************************************************
213 
214 template<typename TRAITS,typename LO,typename GO>
217  const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
218  const Teuchos::ParameterList& p,
219  bool /* useDiscreteAdjoint */)
220  : rowIndexers_(rIndexers)
221  , colIndexers_(cIndexers)
222  , globalDataKey_("Residual Scatter Container")
223 {
224  std::string scatterName = p.get<std::string>("Scatter Name");
225  scatterHolder_ =
226  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
227 
228  // get names to be evaluated
229  const std::vector<std::string>& names =
230  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
231 
232  // grab map from evaluated names to field names
233  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
234 
236  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
237 
238  // build the vector of fields that this is dependent on
239  scatterFields_.resize(names.size());
240  for (std::size_t eq = 0; eq < names.size(); ++eq) {
241  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
242 
243  // tell the field manager that we depend on this field
244  this->addDependentField(scatterFields_[eq]);
245  }
246 
247  // this is what this evaluator provides
248  this->addEvaluatedField(*scatterHolder_);
249 
250  if (p.isType<std::string>("Global Data Key"))
251  globalDataKey_ = p.get<std::string>("Global Data Key");
252 
253  this->setName(scatterName+" Scatter Tangent");
254 }
255 
256 // **********************************************************************
257 template<typename TRAITS,typename LO,typename GO>
259 postRegistrationSetup(typename TRAITS::SetupData /* d */,
260  PHX::FieldManager<TRAITS>& /* fm */)
261 {
262  indexerIds_.resize(scatterFields_.size());
263  subFieldIds_.resize(scatterFields_.size());
264 
265  // load required field numbers for fast use
266  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
267  // get field ID from DOF manager
268  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
269 
270  indexerIds_[fd] = getFieldBlock(fieldName,rowIndexers_);
271  subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
272  }
273 }
274 
275 // **********************************************************************
276 template<typename TRAITS,typename LO,typename GO>
278 preEvaluate(typename TRAITS::PreEvalData d)
279 {
280  typedef BlockedEpetraLinearObjContainer BLOC;
281  typedef BlockedEpetraLinearObjContainer ELOC;
282 
283  // extract linear object container
284  Teuchos::RCP<const BLOC> blockedContainer = Teuchos::rcp_dynamic_cast<const BLOC>(d.gedc->getDataObject(globalDataKey_));
285  Teuchos::RCP<const ELOC> epetraContainer = Teuchos::rcp_dynamic_cast<const ELOC>(d.gedc->getDataObject(globalDataKey_));
286 
287  // if its blocked do this
288  if(blockedContainer!=Teuchos::null)
289  r_ = Teuchos::rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(blockedContainer->get_f());
290  else if(epetraContainer!=Teuchos::null) // if its straight up epetra do this
291  r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
292 
293  TEUCHOS_ASSERT(r_!=Teuchos::null);
294 }
295 
296 // **********************************************************************
297 template<typename TRAITS,typename LO,typename GO>
299 evaluateFields(typename TRAITS::EvalData workset)
300 {
301  TEUCHOS_ASSERT(false);
302 
303  using Teuchos::RCP;
304  using Teuchos::ptrFromRef;
305  using Teuchos::rcp_dynamic_cast;
306 
307  using Thyra::VectorBase;
308  using Thyra::SpmdVectorBase;
310 
311  // for convenience pull out some objects from workset
312  std::string blockId = this->wda(workset).block_id;
313  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
314 
315  // NOTE: A reordering of these loops will likely improve performance
316  // The "getGIDFieldOffsets may be expensive. However the
317  // "getElementGIDs" can be cheaper. However the lookup for LIDs
318  // may be more expensive!
319 
320  // loop over each field to be scattered
322  for (std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
323  int indexerId = indexerIds_[fieldIndex];
324  int subFieldNum = subFieldIds_[fieldIndex];
325 
326  // grab local data for inputing
327  rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(indexerId))->getNonconstLocalData(ptrFromRef(local_r));
328 
329  auto subRowIndexer = rowIndexers_[indexerId];
330  const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
331 
332  // scatter operation for each cell in workset
333  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
334  std::size_t cellLocalId = localCellIds[worksetCellIndex];
335 
336  auto LIDs = subRowIndexer->getElementLIDs(cellLocalId);
337 
338  // loop over basis functions
339  for(std::size_t basis=0;basis<elmtOffset.size();basis++) {
340  int offset = elmtOffset[basis];
341  int lid = LIDs[offset];
342  local_r[lid] += (scatterFields_[fieldIndex])(worksetCellIndex,basis).val();
343  }
344  }
345  }
346 }
347 
348 // **********************************************************************
349 // Specialization: Jacobian
350 // **********************************************************************
351 
352 template<typename TRAITS,typename LO,typename GO>
355  const std::vector<Teuchos::RCP<const GlobalIndexer> > & cIndexers,
356  const Teuchos::ParameterList& p,
357  bool useDiscreteAdjoint)
358  : rowIndexers_(rIndexers)
359  , colIndexers_(cIndexers)
360  , globalDataKey_("Residual Scatter Container")
361  , useDiscreteAdjoint_(useDiscreteAdjoint)
362 {
363  std::string scatterName = p.get<std::string>("Scatter Name");
364  scatterHolder_ =
365  Teuchos::rcp(new PHX::Tag<ScalarT>(scatterName,Teuchos::rcp(new PHX::MDALayout<Dummy>(0))));
366 
367  // get names to be evaluated
368  const std::vector<std::string>& names =
369  *(p.get< Teuchos::RCP< std::vector<std::string> > >("Dependent Names"));
370 
371  // grab map from evaluated names to field names
372  fieldMap_ = p.get< Teuchos::RCP< std::map<std::string,std::string> > >("Dependent Map");
373 
375  p.get< Teuchos::RCP<const panzer::PureBasis> >("Basis")->functional;
376 
377  // build the vector of fields that this is dependent on
378  scatterFields_.resize(names.size());
379  for (std::size_t eq = 0; eq < names.size(); ++eq) {
380  scatterFields_[eq] = PHX::MDField<const ScalarT,Cell,NODE>(names[eq],dl);
381 
382  // tell the field manager that we depend on this field
383  this->addDependentField(scatterFields_[eq]);
384  }
385 
386  // this is what this evaluator provides
387  this->addEvaluatedField(*scatterHolder_);
388 
389  if (p.isType<std::string>("Global Data Key"))
390  globalDataKey_ = p.get<std::string>("Global Data Key");
391  if (p.isType<bool>("Use Discrete Adjoint"))
392  useDiscreteAdjoint = p.get<bool>("Use Discrete Adjoint");
393 
394  // discrete adjoint does not work with non-square matrices
395  if(useDiscreteAdjoint)
396  { TEUCHOS_ASSERT(colIndexers_.size()==0); }
397 
398  if(colIndexers_.size()==0)
399  colIndexers_ = rowIndexers_;
400 
401  this->setName(scatterName+" Scatter Residual BlockedEpetra (Jacobian)");
402 }
403 
404 // **********************************************************************
405 template<typename TRAITS,typename LO,typename GO>
407 postRegistrationSetup(typename TRAITS::SetupData /* d */,
408  PHX::FieldManager<TRAITS>& /* fm */)
409 {
410  indexerIds_.resize(scatterFields_.size());
411  subFieldIds_.resize(scatterFields_.size());
412 
413  // load required field numbers for fast use
414  for(std::size_t fd=0;fd<scatterFields_.size();++fd) {
415  // get field ID from DOF manager
416  std::string fieldName = fieldMap_->find(scatterFields_[fd].fieldTag().name())->second;
417 
418  indexerIds_[fd] = getFieldBlock(fieldName,rowIndexers_);
419  subFieldIds_[fd] = rowIndexers_[indexerIds_[fd]]->getFieldNum(fieldName);
420  }
421 }
422 
423 // **********************************************************************
424 template<typename TRAITS,typename LO,typename GO>
426 preEvaluate(typename TRAITS::PreEvalData d)
427 {
428  using Teuchos::RCP;
429  using Teuchos::rcp_dynamic_cast;
430 
431  typedef BlockedEpetraLinearObjContainer BLOC;
432  typedef BlockedEpetraLinearObjContainer ELOC;
433 
434  // extract linear object container
435  RCP<const BLOC> blockedContainer = rcp_dynamic_cast<const BLOC>(d.gedc->getDataObject(globalDataKey_));
436  RCP<const ELOC> epetraContainer = rcp_dynamic_cast<const ELOC>(d.gedc->getDataObject(globalDataKey_));
437 
438  // if its blocked do this
439  if(blockedContainer!=Teuchos::null) {
440  r_ = Teuchos::rcp_dynamic_cast<Thyra::ProductVectorBase<double> >(blockedContainer->get_f());
441  Jac_ = rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(blockedContainer->get_A());
442  }
443  else if(epetraContainer!=Teuchos::null) {
444  // if its straight up epetra do this
445  if(epetraContainer->get_f_th()!=Teuchos::null)
446  r_ = Thyra::castOrCreateNonconstProductVectorBase<double>(epetraContainer->get_f_th());
447 
448  // convert it into a blocked operator
449  RCP<Thyra::LinearOpBase<double> > J = blockedContainer->get_A_th();
450  Jac_ = rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(Thyra::nonconstBlock1x1(J));
451  }
452 
453  TEUCHOS_ASSERT(Jac_!=Teuchos::null);
454 }
455 
456 // **********************************************************************
457 template<typename TRAITS,typename LO,typename GO>
459 evaluateFields(typename TRAITS::EvalData workset)
460 {
461  using Teuchos::RCP;
462  using Teuchos::ArrayRCP;
463  using Teuchos::ptrFromRef;
464  using Teuchos::rcp_dynamic_cast;
465 
466  using Thyra::VectorBase;
467  using Thyra::SpmdVectorBase;
470 
471  std::vector<double> jacRow;
472 
473  // for convenience pull out some objects from workset
474  std::string blockId = this->wda(workset).block_id;
475  const std::vector<std::size_t> & localCellIds = this->wda(workset).cell_local_ids;
476 
477  int numFieldBlocks = Teuchos::as<int>(colIndexers_.size());
478 
479  std::vector<int> blockOffsets;
480  computeBlockOffsets(blockId,colIndexers_,blockOffsets);
481 
482  std::unordered_map<std::pair<int,int>,Teuchos::RCP<Epetra_CrsMatrix>,panzer::pair_hash> jacEpetraBlocks;
483 
484  // loop over each field to be scattered
486  for(std::size_t fieldIndex = 0; fieldIndex < scatterFields_.size(); fieldIndex++) {
487  int rowIndexer = indexerIds_[fieldIndex];
488  int subFieldNum = subFieldIds_[fieldIndex];
489 
490  // grab local data for inputing
491  if(r_!=Teuchos::null)
492  rcp_dynamic_cast<SpmdVectorBase<double> >(r_->getNonconstVectorBlock(rowIndexer))->getNonconstLocalData(ptrFromRef(local_r));
493 
494  auto subRowIndexer = rowIndexers_[rowIndexer];
495  const std::vector<int> & elmtOffset = subRowIndexer->getGIDFieldOffsets(blockId,subFieldNum);
496 
497  // scatter operation for each cell in workset
498  for(std::size_t worksetCellIndex=0;worksetCellIndex<localCellIds.size();++worksetCellIndex) {
499  std::size_t cellLocalId = localCellIds[worksetCellIndex];
500 
501  auto rLIDs = subRowIndexer->getElementLIDs(cellLocalId);
502 
503  // loop over the basis functions (currently they are nodes)
504  for(std::size_t rowBasisNum = 0; rowBasisNum < elmtOffset.size(); rowBasisNum++) {
505  const ScalarT scatterField = (scatterFields_[fieldIndex])(worksetCellIndex,rowBasisNum);
506  int rowOffset = elmtOffset[rowBasisNum];
507  int r_lid = rLIDs[rowOffset];
508 
509  // Sum residual
510  if(local_r!=Teuchos::null)
511  local_r[r_lid] += (scatterField.val());
512 
513  // loop over the sensitivity indices: all DOFs on a cell
514  jacRow.resize(scatterField.size());
515 
516  // For Neumann conditions with no dependence on degrees of freedom, there should be no Jacobian contribution
517  if(scatterField.size() == 0)
518  continue;
519 
520  for(int sensIndex=0;sensIndex<scatterField.size();++sensIndex)
521  jacRow[sensIndex] = scatterField.fastAccessDx(sensIndex);
522 
523  // scatter the row to each block
524  for(int colIndexer=0;colIndexer<numFieldBlocks;colIndexer++) {
525  int start = blockOffsets[colIndexer];
526  int end = blockOffsets[colIndexer+1];
527 
528  if(end-start<=0)
529  continue;
530 
531  auto subColIndexer = colIndexers_[colIndexer];
532  auto cLIDs = subColIndexer->getElementLIDs(cellLocalId);
533 
534  TEUCHOS_ASSERT(end-start==Teuchos::as<int>(cLIDs.size()));
535 
536  // check hash table for jacobian sub block
537  std::pair<int,int> blockIndex = useDiscreteAdjoint_ ? std::make_pair(colIndexer,rowIndexer)
538  : std::make_pair(rowIndexer,colIndexer);
539  Teuchos::RCP<Epetra_CrsMatrix> subJac = jacEpetraBlocks[blockIndex];
540 
541  // if you didn't find one before, add it to the hash table
542  if(subJac==Teuchos::null) {
543  Teuchos::RCP<Thyra::LinearOpBase<double> > tOp = Jac_->getNonconstBlock(blockIndex.first,blockIndex.second);
544 
545  // block operator is null, don't do anything (it is excluded)
546  if(Teuchos::is_null(tOp))
547  continue;
548 
549  Teuchos::RCP<Epetra_Operator> eOp = Thyra::get_Epetra_Operator(*tOp);
550  subJac = rcp_dynamic_cast<Epetra_CrsMatrix>(eOp,true);
551  jacEpetraBlocks[blockIndex] = subJac;
552  }
553 
554  // Sum Jacobian
555  if(!useDiscreteAdjoint_) {
556  int err = subJac->SumIntoMyValues(r_lid, end-start, &jacRow[start],&cLIDs[0]);
557  if(err!=0) {
558 
559  std::stringstream ss;
560  ss << "Failed inserting row: " << "LID = " << r_lid << "): ";
561  for(int i=start;i<end;i++)
562  ss << cLIDs[i] << " ";
563  ss << std::endl;
564  ss << "Into block " << rowIndexer << ", " << colIndexer << std::endl;
565 
566  ss << "scatter field = ";
567  scatterFields_[fieldIndex].print(ss);
568  ss << std::endl;
569 
570  TEUCHOS_TEST_FOR_EXCEPTION(err!=0,std::runtime_error,ss.str());
571  }
572  }
573  else {
574  for(std::size_t c=0;c<cLIDs.size();c++) {
575  int err = subJac->SumIntoMyValues(cLIDs[c], 1, &jacRow[start+c],&r_lid);
577  }
578  }
579  }
580  } // end rowBasisNum
581  } // end fieldIndex
582  }
583 }
584 
585 // **********************************************************************
586 
587 #endif
T & get(const std::string &name, T def_value)
bool is_null(const std::shared_ptr< T > &p)
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
void computeBlockOffsets(const std::string &blockId, const std::vector< Teuchos::RCP< GlobalIndexer >> &ugis, std::vector< int > &blockOffsets)
void resize(const size_type n, const T &val=T())
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
int getFieldBlock(const std::string &fieldName, const std::vector< Teuchos::RCP< const GlobalIndexer >> &ugis)
int SumIntoMyValues(int MyRow, int NumEntries, const double *Values, const int *Indices)
Pushes residual values into the residual vector for a Newton-based solve.
void postRegistrationSetup(typename TRAITS::SetupData d, PHX::FieldManager< TRAITS > &vm)
bool isType(const std::string &name) const
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
TransListIter end