|
EpetraExt
Development
|
00001 /* 00002 //@HEADER 00003 // *********************************************************************** 00004 // 00005 // EpetraExt: Epetra Extended - Linear Algebra Services Package 00006 // Copyright (2011) Sandia Corporation 00007 // 00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00009 // the U.S. Government retains certain rights in this software. 00010 // 00011 // Redistribution and use in source and binary forms, with or without 00012 // modification, are permitted provided that the following conditions are 00013 // met: 00014 // 00015 // 1. Redistributions of source code must retain the above copyright 00016 // notice, this list of conditions and the following disclaimer. 00017 // 00018 // 2. Redistributions in binary form must reproduce the above copyright 00019 // notice, this list of conditions and the following disclaimer in the 00020 // documentation and/or other materials provided with the distribution. 00021 // 00022 // 3. Neither the name of the Corporation nor the names of the 00023 // contributors may be used to endorse or promote products derived from 00024 // this software without specific prior written permission. 00025 // 00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00037 // 00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 00039 // 00040 // *********************************************************************** 00041 //@HEADER 00042 */ 00043 00044 #include "EpetraExt_MultiPointModelEvaluator.h" 00045 #include "Epetra_Map.h" 00046 #include "Teuchos_as.hpp" 00047 00048 EpetraExt::MultiPointModelEvaluator::MultiPointModelEvaluator( 00049 Teuchos::RefCountPtr<EpetraExt::ModelEvaluator> underlyingME_, 00050 const Teuchos::RefCountPtr<EpetraExt::MultiComm> &globalComm_, 00051 const std::vector<Epetra_Vector*> initGuessVec_, 00052 Teuchos::RefCountPtr<std::vector< Teuchos::RefCountPtr<Epetra_Vector> > > q_vec_, 00053 Teuchos::RefCountPtr<std::vector< Teuchos::RefCountPtr<Epetra_Vector> > > matching_vec_ 00054 ) : 00055 underlyingME(underlyingME_), 00056 globalComm(globalComm_), 00057 q_vec(q_vec_), 00058 underlyingNg(0), 00059 timeStepsOnTimeDomain(globalComm_->NumTimeStepsOnDomain()), 00060 numTimeDomains(globalComm_->NumSubDomains()), 00061 timeDomain(globalComm_->SubDomainRank()), 00062 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00063 rowStencil_int(0), 00064 #endif 00065 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00066 rowStencil_LL(0), 00067 #endif 00068 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00069 rowIndex_int(0), 00070 #endif 00071 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00072 rowIndex_LL(0), 00073 #endif 00074 matching_vec(matching_vec_) 00075 { 00076 using Teuchos::as; 00077 if (globalComm->MyPID()==0) { 00078 std::cout << "----------MultiPoint Partition Info------------" 00079 << "\n\tNumProcs = " << globalComm->NumProc() 00080 << "\n\tSpatial Decomposition = " << globalComm->SubDomainComm().NumProc() 00081 << "\n\tNumber of Domains = " << numTimeDomains 00082 << "\n\tSteps on Domain 0 = " << timeStepsOnTimeDomain 00083 << "\n\tTotal Number of Steps = " << globalComm->NumTimeSteps(); 00084 std::cout << "\n-----------------------------------------------" << std::endl; 00085 } 00086 00087 // Construct global block matrix graph from split W and stencil, 00088 // which is just diagonal in this case 00089 00090 split_W = Teuchos::rcp_dynamic_cast<Epetra_RowMatrix>(underlyingME->create_W()); 00091 00092 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00093 if(split_W->RowMatrixRowMap().GlobalIndicesInt()) { 00094 longlong = false; 00095 rowStencil_int = new std::vector< std::vector<int> >(timeStepsOnTimeDomain); 00096 rowIndex_int = new std::vector<int>; 00097 for (int i=0; i < timeStepsOnTimeDomain; i++) { 00098 (*rowStencil_int)[i].push_back(0); 00099 (*rowIndex_int).push_back(i + globalComm->FirstTimeStepOnDomain()); 00100 } 00101 block_W = Teuchos::rcp(new EpetraExt::BlockCrsMatrix(*split_W, 00102 *rowStencil_int, *rowIndex_int, *globalComm)); 00103 } 00104 else 00105 #endif 00106 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00107 if(split_W->RowMatrixRowMap().GlobalIndicesInt()) { 00108 longlong = true; 00109 rowStencil_LL = new std::vector< std::vector<long long> >(timeStepsOnTimeDomain); 00110 rowIndex_LL = new std::vector<long long>; 00111 for (int i=0; i < timeStepsOnTimeDomain; i++) { 00112 (*rowStencil_LL)[i].push_back(0); 00113 (*rowIndex_LL).push_back(i + globalComm->FirstTimeStepOnDomain()); 00114 } 00115 block_W = Teuchos::rcp(new EpetraExt::BlockCrsMatrix(*split_W, 00116 *rowStencil_LL, *rowIndex_LL, *globalComm)); 00117 } 00118 else 00119 #endif 00120 throw "EpetraExt::MultiPointModelEvaluator::MultiPointModelEvaluator: Global indices unknown"; 00121 00122 // Test for g vector 00123 EpetraExt::ModelEvaluator::OutArgs underlyingOutArgs = underlyingME->createOutArgs(); 00124 00125 underlyingNg = underlyingOutArgs.Ng(); 00126 if (underlyingNg) { 00127 if (underlyingOutArgs.supports(OUT_ARG_DgDp,0,0).supports(DERIV_TRANS_MV_BY_ROW)) 00128 orientation_DgDp = DERIV_TRANS_MV_BY_ROW; 00129 else 00130 orientation_DgDp = DERIV_MV_BY_COL; 00131 } 00132 00133 // This code assumes 2 parameter vectors, 1 for opt, second for MultiPoint states 00134 TEUCHOS_TEST_FOR_EXCEPT(underlyingOutArgs.Np()!=2); 00135 00136 // temporary quantities 00137 const Epetra_Map& split_map = split_W->RowMatrixRowMap(); 00138 num_p0 = underlyingME_->get_p_map(0)->NumMyElements(); 00139 if (underlyingNg) num_g0 = underlyingME_->get_g_map(0)->NumMyElements(); 00140 else num_g0 = 0; 00141 num_dg0dp0 = num_g0 * num_p0; 00142 00143 // Construct global solution vector, residual vector -- local storage 00144 block_x = new EpetraExt::BlockVector(split_map, block_W->RowMap()); 00145 block_f = new EpetraExt::BlockVector(*block_x); 00146 block_DfDp = new EpetraExt::BlockMultiVector(split_map, block_W->RowMap(), num_p0); 00147 if (underlyingNg) 00148 block_DgDx = new EpetraExt::BlockMultiVector(split_map, block_W->RowMap(), num_g0); 00149 00150 // Allocate local storage of epetra vectors 00151 split_x = Teuchos::rcp(new Epetra_Vector(split_map)); 00152 split_f = Teuchos::rcp(new Epetra_Vector(split_map)); 00153 split_DfDp = Teuchos::rcp(new Epetra_MultiVector(split_map, num_p0)); 00154 if (underlyingNg) 00155 split_DgDx = Teuchos::rcp(new Epetra_MultiVector(split_map, num_g0)); 00156 if (underlyingNg) { 00157 if(orientation_DgDp == DERIV_TRANS_MV_BY_ROW) 00158 split_DgDp = Teuchos::rcp(new Epetra_MultiVector(*(underlyingME_->get_p_map(0)), num_g0)); 00159 else 00160 split_DgDp = Teuchos::rcp(new Epetra_MultiVector(*(underlyingME_->get_g_map(0)), num_p0)); 00161 } 00162 if (underlyingNg) 00163 split_g = Teuchos::rcp(new Epetra_Vector(*(underlyingME_->get_g_map(0)))); 00164 00165 // Packaging required for getting multivectors back as Derivatives 00166 derivMV_DfDp = new EpetraExt::ModelEvaluator::DerivativeMultiVector(split_DfDp); 00167 deriv_DfDp = new EpetraExt::ModelEvaluator::Derivative(*derivMV_DfDp); 00168 if (underlyingNg) { 00169 derivMV_DgDx = new EpetraExt::ModelEvaluator::DerivativeMultiVector(split_DgDx, DERIV_TRANS_MV_BY_ROW); 00170 deriv_DgDx = new EpetraExt::ModelEvaluator::Derivative(*derivMV_DgDx); 00171 derivMV_DgDp = new EpetraExt::ModelEvaluator::DerivativeMultiVector(split_DgDp, orientation_DgDp); 00172 deriv_DgDp = new EpetraExt::ModelEvaluator::Derivative(*derivMV_DgDp); 00173 } 00174 00175 // For 4D, we will need the overlap vector and importer between them 00176 // Overlap not needed for MultiPoint -- no overlap between blocks 00177 /* solutionOverlap = new EpetraExt::BlockVector(split_W->RowMatrixRowMap(), 00178 block_W->ColMap()); 00179 overlapImporter = new Epetra_Import(solutionOverlap->Map(), block_x->Map()); 00180 */ 00181 00182 // Load initial guess into block solution vector 00183 solution_init = Teuchos::rcp(new EpetraExt::BlockVector(*block_x)); 00184 00185 if(longlong) { 00186 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00187 for (int i=0; i < timeStepsOnTimeDomain; i++) 00188 solution_init->LoadBlockValues(*(initGuessVec_[i]), (*rowIndex_LL)[i]); 00189 #endif 00190 } 00191 else { 00192 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00193 for (int i=0; i < timeStepsOnTimeDomain; i++) 00194 solution_init->LoadBlockValues(*(initGuessVec_[i]), (*rowIndex_int)[i]); 00195 #endif 00196 } 00197 00198 00199 //Prepare logic for matching problem 00200 if (Teuchos::is_null(matching_vec)) matchingProblem = false; 00201 else matchingProblem = true; 00202 00203 if (matchingProblem) { 00204 TEUCHOS_TEST_FOR_EXCEPT(as<int>(matching_vec->size())!=timeStepsOnTimeDomain); 00205 TEUCHOS_TEST_FOR_EXCEPT(!(*matching_vec)[0]->Map().SameAs(*(underlyingME_->get_g_map(0)))); 00206 TEUCHOS_TEST_FOR_EXCEPT(num_g0 != 1); //This restriction may be lifted later 00207 } 00208 } 00209 00210 EpetraExt::MultiPointModelEvaluator::~MultiPointModelEvaluator() 00211 { 00212 delete block_x; 00213 delete block_f; 00214 delete block_DfDp; 00215 if (underlyingNg) delete block_DgDx; 00216 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00217 delete rowStencil_int; 00218 delete rowIndex_int; 00219 #endif 00220 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00221 delete rowStencil_LL; 00222 delete rowIndex_LL; 00223 #endif 00224 00225 delete derivMV_DfDp; 00226 delete deriv_DfDp; 00227 if (underlyingNg) { 00228 delete derivMV_DgDx; 00229 delete deriv_DgDx; 00230 delete derivMV_DgDp; 00231 delete deriv_DgDp; 00232 } 00233 } 00234 00235 Teuchos::RefCountPtr<const Epetra_Map> EpetraExt::MultiPointModelEvaluator::get_x_map() const 00236 { 00237 return Teuchos::rcp(&(block_W->OperatorDomainMap()), false); 00238 } 00239 00240 Teuchos::RefCountPtr<const Epetra_Map> EpetraExt::MultiPointModelEvaluator::get_f_map() const 00241 { 00242 return get_x_map(); 00243 } 00244 00245 Teuchos::RefCountPtr<const Epetra_Map> EpetraExt::MultiPointModelEvaluator::get_p_map(int l) const 00246 { 00247 return underlyingME->get_p_map(l); 00248 } 00249 00250 Teuchos::RefCountPtr<const Epetra_Map> EpetraExt::MultiPointModelEvaluator::get_g_map(int j) const 00251 { 00252 return underlyingME->get_g_map(j); 00253 } 00254 00255 Teuchos::RefCountPtr<const Epetra_Vector> EpetraExt::MultiPointModelEvaluator::get_x_init() const 00256 { 00257 return solution_init; 00258 } 00259 00260 Teuchos::RefCountPtr<const Epetra_Vector> EpetraExt::MultiPointModelEvaluator::get_p_init(int l) const 00261 { 00262 return underlyingME->get_p_init(l); 00263 } 00264 00265 Teuchos::RefCountPtr<Epetra_Operator> EpetraExt::MultiPointModelEvaluator::create_W() const 00266 { 00267 return block_W; 00268 } 00269 00270 EpetraExt::ModelEvaluator::InArgs EpetraExt::MultiPointModelEvaluator::createInArgs() const 00271 { 00272 //return underlyingME->createInArgs(); 00273 InArgsSetup inArgs; 00274 inArgs.setModelEvalDescription(this->description()); 00275 inArgs.set_Np(1); 00276 inArgs.setSupports(IN_ARG_x,true); 00277 return inArgs; 00278 } 00279 00280 EpetraExt::ModelEvaluator::OutArgs EpetraExt::MultiPointModelEvaluator::createOutArgs() const 00281 { 00282 //return underlyingME->createOutArgs(); 00283 OutArgsSetup outArgs; 00284 outArgs.setModelEvalDescription(this->description()); 00285 outArgs.set_Np_Ng(1, underlyingNg); 00286 outArgs.setSupports(OUT_ARG_f,true); 00287 outArgs.setSupports(OUT_ARG_W,true); 00288 outArgs.set_W_properties( 00289 DerivativeProperties( 00290 DERIV_LINEARITY_NONCONST 00291 ,DERIV_RANK_FULL 00292 ,true // supportsAdjoint 00293 ) 00294 ); 00295 outArgs.setSupports(OUT_ARG_DfDp,0,DERIV_MV_BY_COL); 00296 outArgs.set_DfDp_properties( 00297 0,DerivativeProperties( 00298 DERIV_LINEARITY_CONST 00299 ,DERIV_RANK_DEFICIENT 00300 ,true // supportsAdjoint 00301 ) 00302 ); 00303 00304 if (underlyingNg) { 00305 outArgs.setSupports(OUT_ARG_DgDx,0,DERIV_TRANS_MV_BY_ROW); 00306 outArgs.set_DgDx_properties( 00307 0,DerivativeProperties( 00308 DERIV_LINEARITY_NONCONST 00309 ,DERIV_RANK_DEFICIENT 00310 ,true // supportsAdjoint 00311 ) 00312 ); 00313 outArgs.setSupports(OUT_ARG_DgDp,0,0, orientation_DgDp); 00314 outArgs.set_DgDp_properties( 00315 0,0,DerivativeProperties( 00316 DERIV_LINEARITY_NONCONST 00317 ,DERIV_RANK_DEFICIENT 00318 ,true // supportsAdjoint 00319 ) 00320 ); 00321 } 00322 return outArgs; 00323 } 00324 00325 void EpetraExt::MultiPointModelEvaluator::evalModel( const InArgs& inArgs, 00326 const OutArgs& outArgs ) const 00327 { 00328 00329 EpetraExt::ModelEvaluator::InArgs underlyingInArgs = underlyingME->createInArgs(); 00330 EpetraExt::ModelEvaluator::OutArgs underlyingOutArgs = underlyingME->createOutArgs(); 00331 00332 //temp code for multipoint param q vec 00333 /* 00334 Teuchos::RefCountPtr<Epetra_Vector> q = 00335 Teuchos::rcp(new Epetra_Vector(*(underlyingME->get_p_map(1)))); 00336 */ 00337 00338 // Parse InArgs 00339 Teuchos::RefCountPtr<const Epetra_Vector> p_in = inArgs.get_p(0); 00340 if (p_in.get()) underlyingInArgs.set_p(0, p_in); 00341 00342 Teuchos::RefCountPtr<const Epetra_Vector> x_in = inArgs.get_x(); 00343 block_x->Epetra_Vector::operator=(*x_in); //copy into block vector 00344 00345 // Parse OutArgs 00346 Teuchos::RefCountPtr<Epetra_Vector> f_out = outArgs.get_f(); 00347 00348 Teuchos::RefCountPtr<Epetra_Operator> W_out = outArgs.get_W(); 00349 Teuchos::RefCountPtr<EpetraExt::BlockCrsMatrix> W_block = 00350 Teuchos::rcp_dynamic_cast<EpetraExt::BlockCrsMatrix>(W_out); 00351 00352 Teuchos::RefCountPtr<Epetra_Vector> g_out; 00353 if (underlyingNg) g_out = outArgs.get_g(0); 00354 if (g_out.get()) g_out->PutScalar(0.0); 00355 00356 EpetraExt::ModelEvaluator::Derivative DfDp_out = outArgs.get_DfDp(0); 00357 00358 EpetraExt::ModelEvaluator::Derivative DgDx_out; 00359 EpetraExt::ModelEvaluator::Derivative DgDp_out; 00360 if (underlyingNg) { 00361 DgDx_out = outArgs.get_DgDx(0); 00362 DgDp_out = outArgs.get_DgDp(0,0); 00363 if (!DgDx_out.isEmpty()) DgDx_out.getMultiVector()->PutScalar(0.0); 00364 if (!DgDp_out.isEmpty()) DgDp_out.getMultiVector()->PutScalar(0.0); 00365 } 00366 00367 // For mathcingProblems, g is needed to calc DgDx DgDp, so ask for 00368 // g even if it isn't requested. 00369 bool need_g = g_out.get(); 00370 if (matchingProblem) 00371 if ( !DgDx_out.isEmpty() || !DgDp_out.isEmpty() ) need_g = true; 00372 00373 00374 // Begin loop over Points (steps) owned on this proc 00375 for (int i=0; i < timeStepsOnTimeDomain; i++) { 00376 00377 // Set MultiPoint parameter vector 00378 underlyingInArgs.set_p(1, (*q_vec)[i]); 00379 00380 // Set InArgs 00381 if(longlong) { 00382 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00383 block_x->ExtractBlockValues(*split_x, (*rowIndex_LL)[i]); 00384 #endif 00385 } 00386 else { 00387 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00388 block_x->ExtractBlockValues(*split_x, (*rowIndex_int)[i]); 00389 #endif 00390 } 00391 underlyingInArgs.set_x(split_x); 00392 00393 // Set OutArgs 00394 if (f_out.get()) underlyingOutArgs.set_f(split_f); 00395 00396 if (need_g) underlyingOutArgs.set_g(0, split_g); 00397 00398 if (W_out.get()) underlyingOutArgs.set_W(split_W); 00399 00400 if (!DfDp_out.isEmpty()) underlyingOutArgs.set_DfDp(0, *deriv_DfDp); 00401 00402 if (!DgDx_out.isEmpty()) underlyingOutArgs.set_DgDx(0, *deriv_DgDx); 00403 00404 if (!DgDp_out.isEmpty()) underlyingOutArgs.set_DgDp(0, 0, *deriv_DgDp); 00405 00406 //********Eval Model ********/ 00407 underlyingME->evalModel(underlyingInArgs, underlyingOutArgs); 00408 //********Eval Model ********/ 00409 00410 // If matchingProblem, modify all g-related quantitites G = 0.5*(g-g*)^2 / g*^2 00411 if (matchingProblem) { 00412 if (need_g) { 00413 double diff = (*split_g)[0] - (*(*matching_vec)[i])[0]; 00414 double nrmlz = fabs((*(*matching_vec)[i])[0]) + 1.0e-6; 00415 (*split_g)[0] = 0.5 * diff * diff/(nrmlz*nrmlz); 00416 if (!DgDx_out.isEmpty()) split_DgDx->Scale(diff/(nrmlz*nrmlz)); 00417 if (!DgDp_out.isEmpty()) split_DgDp->Scale(diff/(nrmlz*nrmlz)); 00418 } 00419 } 00420 00421 // Repackage block components into global block matrx/vector/multivector 00422 if(longlong) { 00423 #ifndef EPETRA_NO_64BIT_GLOBAL_INDICES 00424 if (f_out.get()) block_f->LoadBlockValues(*split_f, (*rowIndex_LL)[i]); 00425 if (W_out.get()) W_block->LoadBlock(*split_W, i, 0); 00426 // note: split_DfDp points inside deriv_DfDp 00427 if (!DfDp_out.isEmpty()) block_DfDp->LoadBlockValues(*split_DfDp, (*rowIndex_LL)[i]); 00428 if (!DgDx_out.isEmpty()) block_DgDx->LoadBlockValues(*split_DgDx, (*rowIndex_LL)[i]); 00429 #endif 00430 } 00431 else { 00432 #ifndef EPETRA_NO_32BIT_GLOBAL_INDICES 00433 if (f_out.get()) block_f->LoadBlockValues(*split_f, (*rowIndex_int)[i]); 00434 if (W_out.get()) W_block->LoadBlock(*split_W, i, 0); 00435 // note: split_DfDp points inside deriv_DfDp 00436 if (!DfDp_out.isEmpty()) block_DfDp->LoadBlockValues(*split_DfDp, (*rowIndex_int)[i]); 00437 if (!DgDx_out.isEmpty()) block_DgDx->LoadBlockValues(*split_DgDx, (*rowIndex_int)[i]); 00438 #endif 00439 } 00440 00441 // Assemble multiple steps on this domain into g and dgdp(0) vectors 00442 if (g_out.get()) g_out->Update(1.0, *split_g, 1.0); 00443 00444 if (!DgDp_out.isEmpty()) 00445 DgDp_out.getMultiVector()->Update(1.0, *split_DgDp, 1.0); 00446 00447 } // End loop over multiPoint steps on this domain/cluster 00448 00449 //Copy block vectors into *_out vectors of same size 00450 if (f_out.get()) f_out->operator=(*block_f); 00451 if (!DfDp_out.isEmpty()) 00452 DfDp_out.getMultiVector()->operator=(*block_DfDp); 00453 if (!DgDx_out.isEmpty()) 00454 DgDx_out.getMultiVector()->operator=(*block_DgDx); 00455 00456 //Sum together obj fn contributions from differnt Domains (clusters). 00457 if (numTimeDomains > 1) { 00458 double factorToZeroOutCopies = 0.0; 00459 if (globalComm->SubDomainComm().MyPID()==0) factorToZeroOutCopies = 1.0; 00460 if (g_out.get()) { 00461 (*g_out).Scale(factorToZeroOutCopies); 00462 double* vPtr = &((*g_out)[0]); 00463 Epetra_Vector tmp = *(g_out.get()); 00464 globalComm->SumAll( &(tmp[0]), vPtr, num_g0); 00465 } 00466 if (!DgDp_out.isEmpty()) { 00467 DgDp_out.getMultiVector()->Scale(factorToZeroOutCopies); 00468 double* mvPtr = (*DgDp_out.getMultiVector())[0]; 00469 Epetra_MultiVector tmp = *(DgDp_out.getMultiVector()); 00470 globalComm->SumAll(tmp[0], mvPtr, num_dg0dp0); 00471 } 00472 } 00473 }
1.7.6.1