1 // @HEADER
2 // ************************************************************************
3 //
4 //               Rapid Optimization Library (ROL) Package
5 //                 Copyright (2014) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact lead developers:
38 //              Drew Kouri   (dpkouri@sandia.gov) and
39 //              Denis Ridzal (dridzal@sandia.gov)
40 //
41 // ************************************************************************
42 // @HEADER
43 
44 /*! \file  assembler_def.hpp
45     \brief Finite element assembly class.
46 */
47 
48 #ifndef ROL_PDEOPT_ASSEMBLER_DEF_H
49 #define ROL_PDEOPT_ASSEMBLER_DEF_H
50 
51 #include "assembler.hpp"
52 
53 /*****************************************************************************/
54 /******************* PUBLIC MEMBER FUNCTIONS *********************************/
55 /*****************************************************************************/
56 // Constuctor: Discretization set from ParameterList
57 template<class Real>
Assembler(const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs,const ROL::Ptr<const Teuchos::Comm<int>> & comm,Teuchos::ParameterList & parlist,std::ostream & outStream)58 Assembler<Real>::Assembler(
59         const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs,
60         const ROL::Ptr<const Teuchos::Comm<int>> &comm,
61         Teuchos::ParameterList &parlist,
62         std::ostream &outStream)
63   : isJ1Transposed_(false), isJ2Transposed_(false),
64     isJuoTransposed_(false), isJunTransposed_(false), isJzfTransposed_(false) {
65   setCommunicator(comm,parlist,outStream);
66   setBasis(basisPtrs,basisPtrs,parlist,outStream);
67   setDiscretization(parlist,ROL::nullPtr,outStream);
68   setParallelStructure(parlist,outStream);
69   setCellNodes(outStream);
70 }
71 
72 // Constructor: Discretization set from MeshManager input
73 template<class Real>
Assembler(const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs,const ROL::Ptr<MeshManager<Real>> & meshMgr,const ROL::Ptr<const Teuchos::Comm<int>> & comm,Teuchos::ParameterList & parlist,std::ostream & outStream)74 Assembler<Real>::Assembler(
75         const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs,
76         const ROL::Ptr<MeshManager<Real>> &meshMgr,
77         const ROL::Ptr<const Teuchos::Comm<int>> &comm,
78         Teuchos::ParameterList &parlist,
79         std::ostream &outStream)
80   : isJ1Transposed_(false), isJ2Transposed_(false),
81     isJuoTransposed_(false), isJunTransposed_(false), isJzfTransposed_(false) {
82   setCommunicator(comm,parlist,outStream);
83   setBasis(basisPtrs,basisPtrs,parlist,outStream);
84   setDiscretization(parlist,meshMgr,outStream);
85   setParallelStructure(parlist,outStream);
86   setCellNodes(outStream);
87 }
88 // Constuctor: Discretization set from ParameterList
89 template<class Real>
Assembler(const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs1,const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs2,const ROL::Ptr<const Teuchos::Comm<int>> & comm,Teuchos::ParameterList & parlist,std::ostream & outStream)90 Assembler<Real>::Assembler(
91         const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs1,
92         const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs2,
93         const ROL::Ptr<const Teuchos::Comm<int>> &comm,
94         Teuchos::ParameterList &parlist,
95         std::ostream &outStream)
96   : isJ1Transposed_(false), isJ2Transposed_(false),
97     isJuoTransposed_(false), isJunTransposed_(false), isJzfTransposed_(false) {
98   setCommunicator(comm,parlist,outStream);
99   setBasis(basisPtrs1,basisPtrs2,parlist,outStream);
100   setDiscretization(parlist,ROL::nullPtr,outStream);
101   setParallelStructure(parlist,outStream);
102   setCellNodes(outStream);
103 }
104 
105 // Constructor: Discretization set from MeshManager input
106 template<class Real>
Assembler(const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs1,const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs2,const ROL::Ptr<MeshManager<Real>> & meshMgr,const ROL::Ptr<const Teuchos::Comm<int>> & comm,Teuchos::ParameterList & parlist,std::ostream & outStream)107 Assembler<Real>::Assembler(
108         const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs1,
109         const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs2,
110         const ROL::Ptr<MeshManager<Real>> &meshMgr,
111         const ROL::Ptr<const Teuchos::Comm<int>> &comm,
112         Teuchos::ParameterList &parlist,
113         std::ostream &outStream)
114   : isJ1Transposed_(false), isJ2Transposed_(false),
115     isJuoTransposed_(false), isJunTransposed_(false), isJzfTransposed_(false) {
116   setCommunicator(comm,parlist,outStream);
117   setBasis(basisPtrs1,basisPtrs2,parlist,outStream);
118   setDiscretization(parlist,meshMgr,outStream);
119   setParallelStructure(parlist,outStream);
120   setCellNodes(outStream);
121 }
122 
123 template<class Real>
setCellNodes(PDE<Real> & pde) const124 void Assembler<Real>::setCellNodes(PDE<Real> &pde) const {
125   // Set PDE cell nodes
126   pde.setFieldPattern(dofMgr1_->getFieldPattern(),dofMgr2_->getFieldPattern());
127   pde.setCellNodes(volCellNodes_, bdryCellNodes_, bdryCellLocIds_);
128 }
129 
130 template<class Real>
setCellNodes(DynamicPDE<Real> & pde) const131 void Assembler<Real>::setCellNodes(DynamicPDE<Real> &pde) const {
132   // Set PDE cell nodes
133   pde.setFieldPattern(dofMgr1_->getFieldPattern(),dofMgr2_->getFieldPattern());
134   pde.setCellNodes(volCellNodes_, bdryCellNodes_, bdryCellLocIds_);
135 }
136 
137 /***************************************************************************/
138 /* PDE assembly routines                                                   */
139 /***************************************************************************/
140 template<class Real>
assemblePDEResidual(ROL::Ptr<Tpetra::MultiVector<>> & r,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)141 void Assembler<Real>::assemblePDEResidual(ROL::Ptr<Tpetra::MultiVector<>> &r,
142                                     const ROL::Ptr<PDE<Real>> &pde,
143                                     const ROL::Ptr<const Tpetra::MultiVector<>> &u,
144                                     const ROL::Ptr<const Tpetra::MultiVector<>> &z,
145                                     const ROL::Ptr<const std::vector<Real>> & z_param) {
146   #ifdef ROL_TIMERS
147     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEResidual);
148   #endif
149   // Initialize residual vectors if not done so
150   if ( r == ROL::nullPtr ) { // Unique components of residual vector
151     r = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueResidualMap_, 1, true);
152   }
153   if ( pde_vecR_overlap_ == ROL::nullPtr ) { // Overlapping components of residual vector
154     pde_vecR_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapResidualMap_, 1, true);
155   }
156   // Get u_coeff from u and z_coeff from z
157   ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
158   getCoeffFromStateVector(u_coeff,u);
159   getCoeffFromControlVector(z_coeff,z);
160   // Assemble
161   ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
162   pde->residual(localVal,u_coeff,z_coeff,z_param);
163   assembleFieldVector( r, localVal, pde_vecR_overlap_, dofMgr1_ );
164 }
165 
166 template<class Real>
assemblePDEJacobian1(ROL::Ptr<Tpetra::CrsMatrix<>> & J1,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)167 void Assembler<Real>::assemblePDEJacobian1(ROL::Ptr<Tpetra::CrsMatrix<>> &J1,
168                                      const ROL::Ptr<PDE<Real>> &pde,
169                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
170                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
171                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
172   #ifdef ROL_TIMERS
173     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEJacobian1);
174   #endif
175   try {
176     // Get u_coeff from u and z_coeff from z
177     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
178     getCoeffFromStateVector(u_coeff,u);
179     getCoeffFromControlVector(z_coeff,z);
180     // Initialize Jacobian matrices
181     if ( J1 == ROL::nullPtr ) {
182       J1 = ROL::makePtr<Tpetra::CrsMatrix<>>(matJ1Graph_);
183     }
184     // Assemble
185     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
186     pde->Jacobian_1(localVal,u_coeff,z_coeff,z_param);
187     assembleFieldMatrix( J1, localVal, dofMgr1_, dofMgr1_ );
188     isJ1Transposed_ = false;
189     // Output
190     //Tpetra::MatrixMarket::Writer< Tpetra::CrsMatrix<>> matWriter;
191     //matWriter.writeSparseFile("jacobian_1.txt", J1);
192   }
193   catch ( Exception::Zero & ez ) {
194     throw Exception::Zero(">>> (Assembler::assemblePDEJacobian1): Jacobian is zero.");
195   }
196   catch ( Exception::NotImplemented & eni ) {
197     throw Exception::NotImplemented(">>> (Assembler::assemblePDEJacobian1): Jacobian not implemented.");
198   }
199 }
200 
201 template<class Real>
assemblePDEJacobian2(ROL::Ptr<Tpetra::CrsMatrix<>> & J2,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)202 void Assembler<Real>::assemblePDEJacobian2(ROL::Ptr<Tpetra::CrsMatrix<>> &J2,
203                                      const ROL::Ptr<PDE<Real>> &pde,
204                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
205                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
206                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
207   #ifdef ROL_TIMERS
208     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEJacobian2);
209   #endif
210   try {
211     // Get u_coeff from u and z_coeff from z
212     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
213     getCoeffFromStateVector(u_coeff,u);
214     getCoeffFromControlVector(z_coeff,z);
215     // Initialize Jacobian matrices
216     if ( J2 == ROL::nullPtr ) {
217       J2 = ROL::makePtr<Tpetra::CrsMatrix<>>(matJ2Graph_);
218     }
219     // Assemble
220     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
221     pde->Jacobian_2(localVal,u_coeff,z_coeff,z_param);
222     assembleFieldMatrix( J2, localVal, dofMgr1_, dofMgr2_ );
223     isJ2Transposed_ = false;
224   }
225   catch ( Exception::Zero & ez ) {
226     throw Exception::Zero(">>> (Assembler::assemblePDEJacobian2): Jacobian is zero.");
227   }
228   catch ( Exception::NotImplemented & eni ) {
229     throw Exception::NotImplemented(">>> (Assembler::assemblePDEJacobian2): Jacobian not implemented.");
230   }
231 }
232 
233 template<class Real>
assemblePDEJacobian3(ROL::Ptr<Tpetra::MultiVector<>> & J3,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)234 void Assembler<Real>::assemblePDEJacobian3(ROL::Ptr<Tpetra::MultiVector<>> &J3,
235                                      const ROL::Ptr<PDE<Real>> &pde,
236                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
237                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
238                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
239   #ifdef ROL_TIMERS
240     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEJacobian3);
241   #endif
242   if ( z_param != ROL::nullPtr ) {
243     try {
244       int size = static_cast<int>(z_param->size());
245       // Get u_coeff from u and z_coeff from z
246       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
247       getCoeffFromStateVector(u_coeff,u);
248       getCoeffFromControlVector(z_coeff,z);
249       // Initialize Jacobian storage if not done so already
250       if (J3 == ROL::nullPtr) {
251         J3 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueResidualMap_, size, true);
252       }
253       if ( pde_vecJ3_overlap_ == ROL::nullPtr) {
254         pde_vecJ3_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapResidualMap_, size, true);
255       }
256       // Assemble
257       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
258       pde->Jacobian_3(localVal,u_coeff,z_coeff,z_param);
259       assembleParamFieldMatrix( J3, localVal, pde_vecJ3_overlap_, dofMgr1_ );
260     }
261     catch ( Exception::Zero & ez ) {
262       throw Exception::Zero(">>> (Assembler::assemblePDEJacobian3): Jacobian is zero.");
263     }
264     catch ( Exception::NotImplemented & eni ) {
265       throw Exception::NotImplemented(">>> (Assembler::assemblePDEJacobian3): Jacobian not implemented.");
266     }
267   }
268   else {
269     throw Exception::NotImplemented(">>> (Assembler::assemblePDEJacobian3): Jacobian not implemented.");
270   }
271 }
272 
273 template<class Real>
assemblePDEHessian11(ROL::Ptr<Tpetra::CrsMatrix<>> & H11,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)274 void Assembler<Real>::assemblePDEHessian11(ROL::Ptr<Tpetra::CrsMatrix<>> &H11,
275                                      const ROL::Ptr<PDE<Real>> &pde,
276                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
277                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
278                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
279                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
280   #ifdef ROL_TIMERS
281     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian11);
282   #endif
283   try {
284     // Get u_coeff from u and z_coeff from z
285     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
286     getCoeffFromStateVector(u_coeff,u);
287     getCoeffFromControlVector(z_coeff,z);
288     getCoeffFromStateVector(l_coeff,l);
289     // Initialize Hessian storage if not done so already
290     if ( H11 == ROL::nullPtr ) {
291       H11 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
292     }
293     // Assemble
294     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
295     pde->Hessian_11(localVal,l_coeff,u_coeff,z_coeff,z_param);
296     assembleFieldMatrix( H11, localVal, dofMgr1_, dofMgr1_ );
297   }
298   catch (Exception::Zero &ez) {
299     throw Exception::Zero(">>> (Assembler::assemblePDEHessian11): Hessian is zero.");
300   }
301   catch (Exception::NotImplemented &eni) {
302     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian11): Hessian not implemented.");
303   }
304 }
305 
306 template<class Real>
assemblePDEHessian12(ROL::Ptr<Tpetra::CrsMatrix<>> & H12,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)307 void Assembler<Real>::assemblePDEHessian12(ROL::Ptr<Tpetra::CrsMatrix<>> &H12,
308                                      const ROL::Ptr<PDE<Real>> &pde,
309                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
310                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
311                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
312                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
313   #ifdef ROL_TIMERS
314     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian12);
315   #endif
316   try {
317     // Get u_coeff from u and z_coeff from z
318     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
319     getCoeffFromStateVector(u_coeff,u);
320     getCoeffFromControlVector(z_coeff,z);
321     getCoeffFromStateVector(l_coeff,l);
322     // Initialize Hessian storage if not done so already
323     if ( H12 == ROL::nullPtr ) {
324       H12 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH12Graph_);
325     }
326     // Assemble
327     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
328     pde->Hessian_12(localVal,l_coeff,u_coeff,z_coeff,z_param);
329     assembleFieldMatrix( H12, localVal, dofMgr2_, dofMgr1_ );
330   }
331   catch (Exception::Zero &ez) {
332     throw Exception::Zero(">>> (Assembler::assemblePDEHessian12): Hessian is zero.");
333   }
334   catch (Exception::NotImplemented &eni) {
335     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian12): Hessian not implemented.");
336   }
337 }
338 
339 template<class Real>
assemblePDEHessian13(ROL::Ptr<Tpetra::MultiVector<>> & H13,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)340 void Assembler<Real>::assemblePDEHessian13(ROL::Ptr<Tpetra::MultiVector<>> &H13,
341                                      const ROL::Ptr<PDE<Real>> &pde,
342                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
343                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
344                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
345                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
346   #ifdef ROL_TIMERS
347     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian13);
348   #endif
349   if ( z_param != ROL::nullPtr ) {
350     try {
351       int size = static_cast<int>(z_param->size());
352       // Get u_coeff from u, z_coeff from z and l_coeff from l
353       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
354       getCoeffFromStateVector(u_coeff,u);
355       getCoeffFromControlVector(z_coeff,z);
356       getCoeffFromStateVector(l_coeff,l);
357       // Initialize Jacobian storage if not done so already
358       if (H13 == ROL::nullPtr) {
359         H13 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, size, true);
360       }
361       if ( pde_vecH13_overlap_ == ROL::nullPtr) {
362         pde_vecH13_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, size, true);
363       }
364       // Assemble
365       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
366       pde->Hessian_13(localVal,l_coeff,u_coeff,z_coeff,z_param);
367       assembleParamFieldMatrix( H13, localVal, pde_vecH13_overlap_, dofMgr1_ );
368     }
369     catch ( Exception::Zero & ez ) {
370       throw Exception::Zero(">>> (Assembler::assemblePDEHessian13): Hessian is zero.");
371     }
372     catch ( Exception::NotImplemented & eni ) {
373       throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian13): Hessian not implemented.");
374     }
375   }
376   else {
377     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian13): Hessian not implemented.");
378   }
379 }
380 
381 template<class Real>
assemblePDEHessian21(ROL::Ptr<Tpetra::CrsMatrix<>> & H21,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)382 void Assembler<Real>::assemblePDEHessian21(ROL::Ptr<Tpetra::CrsMatrix<>> &H21,
383                                      const ROL::Ptr<PDE<Real>> &pde,
384                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
385                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
386                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
387                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
388   #ifdef ROL_TIMERS
389     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian21);
390   #endif
391   try {
392     // Get u_coeff from u and z_coeff from z
393     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
394     getCoeffFromStateVector(u_coeff,u);
395     getCoeffFromControlVector(z_coeff,z);
396     getCoeffFromStateVector(l_coeff,l);
397     // Initialize Hessian storage if not done so already
398     if ( H21 == ROL::nullPtr ) {
399       H21 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH21Graph_);
400     }
401     // Assemble
402     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
403     pde->Hessian_21(localVal,l_coeff,u_coeff,z_coeff,z_param);
404     assembleFieldMatrix( H21, localVal, dofMgr1_, dofMgr2_ );
405   }
406   catch (Exception::Zero &ez) {
407     throw Exception::Zero(">>> (Assembler::assemblePDEHessian21): Hessian is zero.");
408   }
409   catch (Exception::NotImplemented &eni) {
410     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian21): Hessian not implemented.");
411   }
412 }
413 
414 template<class Real>
assemblePDEHessian22(ROL::Ptr<Tpetra::CrsMatrix<>> & H22,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)415 void Assembler<Real>::assemblePDEHessian22(ROL::Ptr<Tpetra::CrsMatrix<>> &H22,
416                                      const ROL::Ptr<PDE<Real>> &pde,
417                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
418                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
419                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
420                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
421   #ifdef ROL_TIMERS
422     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian22);
423   #endif
424   try {
425     // Get u_coeff from u and z_coeff from z
426     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
427     getCoeffFromStateVector(u_coeff,u);
428     getCoeffFromControlVector(z_coeff,z);
429     getCoeffFromStateVector(l_coeff,l);
430     // Initialize Hessian storage if not done so already
431     if ( H22 == ROL::nullPtr ) {
432       H22 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH22Graph_);
433     }
434     // Assemble
435     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
436     pde->Hessian_22(localVal,l_coeff,u_coeff,z_coeff,z_param);
437     assembleFieldMatrix( H22, localVal, dofMgr2_, dofMgr2_ );
438   }
439   catch (Exception::Zero &ez) {
440     throw Exception::Zero(">>> (Assembler::assemblePDEHessian22): Hessian is zero.");
441   }
442   catch (Exception::NotImplemented &eni) {
443     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian22): Hessian not implemented.");
444   }
445 }
446 
447 template<class Real>
assemblePDEHessian23(ROL::Ptr<Tpetra::MultiVector<>> & H23,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)448 void Assembler<Real>::assemblePDEHessian23(ROL::Ptr<Tpetra::MultiVector<>> &H23,
449                                      const ROL::Ptr<PDE<Real>> &pde,
450                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
451                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
452                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
453                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
454   #ifdef ROL_TIMERS
455     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian23);
456   #endif
457   if ( z_param != ROL::nullPtr ) {
458     try {
459       int size = static_cast<int>(z_param->size());
460       // Get u_coeff from u, z_coeff from z and l_coeff from l
461       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
462       getCoeffFromStateVector(u_coeff,u);
463       getCoeffFromControlVector(z_coeff,z);
464       getCoeffFromStateVector(l_coeff,l);
465       // Initialize Jacobian storage if not done so already
466       if (H23 == ROL::nullPtr) {
467         H23 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, size, true);
468       }
469       if ( pde_vecH23_overlap_ == ROL::nullPtr) {
470         pde_vecH23_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, size, true);
471       }
472       // Assemble
473       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
474       pde->Hessian_23(localVal,l_coeff,u_coeff,z_coeff,z_param);
475       assembleParamFieldMatrix( H23, localVal, pde_vecH23_overlap_, dofMgr2_ );
476     }
477     catch ( Exception::Zero & ez ) {
478       throw Exception::Zero(">>> (Assembler::assemblePDEHessian23): Hessian is zero.");
479     }
480     catch ( Exception::NotImplemented & eni ) {
481       throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian23): Hessian not implemented.");
482     }
483   }
484   else {
485     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian23): Hessian not implemented.");
486   }
487 }
488 
489 template<class Real>
assemblePDEHessian31(ROL::Ptr<Tpetra::MultiVector<>> & H31,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)490 void Assembler<Real>::assemblePDEHessian31(ROL::Ptr<Tpetra::MultiVector<>> &H31,
491                                      const ROL::Ptr<PDE<Real>> &pde,
492                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
493                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
494                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
495                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
496   #ifdef ROL_TIMERS
497     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian31);
498   #endif
499   assemblePDEHessian13(H31,pde,l,u,z,z_param);
500 }
501 
502 template<class Real>
assemblePDEHessian32(ROL::Ptr<Tpetra::MultiVector<>> & H32,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)503 void Assembler<Real>::assemblePDEHessian32(ROL::Ptr<Tpetra::MultiVector<>> &H32,
504                                      const ROL::Ptr<PDE<Real>> &pde,
505                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
506                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
507                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
508                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
509   #ifdef ROL_TIMERS
510     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian32);
511   #endif
512   assemblePDEHessian23(H32,pde,l,u,z,z_param);
513 }
514 
515 template<class Real>
assemblePDEHessian33(ROL::Ptr<std::vector<std::vector<Real>>> & H33,const ROL::Ptr<PDE<Real>> & pde,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)516 void Assembler<Real>::assemblePDEHessian33(ROL::Ptr<std::vector<std::vector<Real>>> &H33,
517                                      const ROL::Ptr<PDE<Real>> &pde,
518                                      const ROL::Ptr<const Tpetra::MultiVector<>> &l,
519                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
520                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
521                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
522   #ifdef ROL_TIMERS
523     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssemblePDEHessian33);
524   #endif
525   if ( z_param != ROL::nullPtr ) {
526     try {
527       int size = static_cast<int>(z_param->size());
528       // Get u_coeff from u, z_coeff from z and l_coeff from l
529       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff, l_coeff;
530       getCoeffFromStateVector(u_coeff,u);
531       getCoeffFromControlVector(z_coeff,z);
532       getCoeffFromStateVector(l_coeff,l);
533       // Initialize Jacobian storage if not done so already
534       if (H33 == ROL::nullPtr) {
535         std::vector<Real> col(size,static_cast<Real>(0));
536         H33 = ROL::makePtr<std::vector<std::vector<Real>>>(size,col);
537       }
538       // Assemble
539       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> tmp(size,ROL::nullPtr);
540       std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> localVal(size,tmp);
541       pde->Hessian_33(localVal,l_coeff,u_coeff,z_coeff,z_param);
542       assembleParamMatrix( H33, localVal, dofMgr1_ );
543     }
544     catch ( Exception::Zero & ez ) {
545       throw Exception::Zero(">>> (Assembler::assemblePDEHessian33): Hessian is zero.");
546     }
547     catch ( Exception::NotImplemented & eni ) {
548       throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian33): Hessian not implemented.");
549     }
550   }
551   else {
552     throw Exception::NotImplemented(">>> (Assembler::assemblePDEHessian33): Hessian not implemented.");
553   }
554 }
555 /***************************************************************************/
556 /* End of PDE assembly routines.                                           */
557 /***************************************************************************/
558 
559 /***************************************************************************/
560 /* DynamicPDE assembly routines                                            */
561 /***************************************************************************/
562 template<class Real>
assembleDynPDEResidual(ROL::Ptr<Tpetra::MultiVector<>> & r,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)563 void Assembler<Real>::assembleDynPDEResidual(ROL::Ptr<Tpetra::MultiVector<>> &r,
564                                        const ROL::Ptr<DynamicPDE<Real>> &pde,
565                                        const ROL::TimeStamp<Real> &ts,
566                                        const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
567                                        const ROL::Ptr<const Tpetra::MultiVector<>> &un,
568                                        const ROL::Ptr<const Tpetra::MultiVector<>> &z,
569                                        const ROL::Ptr<const std::vector<Real>> &z_param) {
570   #ifdef ROL_TIMERS
571     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEResidual);
572   #endif
573   // Initialize residual vectors if not done so
574   if ( r == ROL::nullPtr ) { // Unique components of residual vector
575     r = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueResidualMap_, 1, true);
576   }
577   if ( pde_vecR_overlap_ == ROL::nullPtr ) { // Overlapping components of residual vector
578     pde_vecR_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapResidualMap_, 1, true);
579   }
580   // Get u_coeff from u and z_coeff from z
581   ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff;
582   getCoeffFromStateVector(uo_coeff,uo);
583   getCoeffFromStateVector(un_coeff,un);
584   getCoeffFromControlVector(z_coeff,z);
585   // Assemble
586   ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
587   pde->residual(localVal,ts,uo_coeff,un_coeff,z_coeff,z_param);
588   assembleFieldVector( r, localVal, pde_vecR_overlap_, dofMgr1_ );
589 }
590 
591 template<class Real>
assembleDynPDEJacobian_uo(ROL::Ptr<Tpetra::CrsMatrix<>> & J,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)592 void Assembler<Real>::assembleDynPDEJacobian_uo(ROL::Ptr<Tpetra::CrsMatrix<>> &J,
593                                           const ROL::Ptr<DynamicPDE<Real>> &pde,
594                                           const ROL::TimeStamp<Real> &ts,
595                                           const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
596                                           const ROL::Ptr<const Tpetra::MultiVector<>> &un,
597                                           const ROL::Ptr<const Tpetra::MultiVector<>> &z,
598                                           const ROL::Ptr<const std::vector<Real>> &z_param) {
599   #ifdef ROL_TIMERS
600     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEJacobian_uo);
601   #endif
602   try {
603     // Get u_coeff from u and z_coeff from z
604     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff;
605     getCoeffFromStateVector(uo_coeff,uo);
606     getCoeffFromStateVector(un_coeff,un);
607     getCoeffFromControlVector(z_coeff,z);
608     // Initialize Jacobian matrices
609     if ( J == ROL::nullPtr ) {
610       J = ROL::makePtr<Tpetra::CrsMatrix<>>(matJ1Graph_);
611     }
612     // Assemble
613     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
614     pde->Jacobian_uo(localVal,ts,uo_coeff,un_coeff,z_coeff,z_param);
615     assembleFieldMatrix( J, localVal, dofMgr1_, dofMgr1_ );
616     isJuoTransposed_ = false;
617   }
618   catch ( Exception::Zero & ez ) {
619     throw Exception::Zero(">>> (Assembler::assembleDynPDEJacobian_uo): Jacobian is zero.");
620   }
621   catch ( Exception::NotImplemented & eni ) {
622     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEJacobian_uo): Jacobian not implemented.");
623   }
624 }
625 
626 template<class Real>
assembleDynPDEJacobian_un(ROL::Ptr<Tpetra::CrsMatrix<>> & J,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)627 void Assembler<Real>::assembleDynPDEJacobian_un(ROL::Ptr<Tpetra::CrsMatrix<>> &J,
628                                           const ROL::Ptr<DynamicPDE<Real>> &pde,
629                                           const ROL::TimeStamp<Real> &ts,
630                                           const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
631                                           const ROL::Ptr<const Tpetra::MultiVector<>> &un,
632                                           const ROL::Ptr<const Tpetra::MultiVector<>> &z,
633                                           const ROL::Ptr<const std::vector<Real>> &z_param) {
634   #ifdef ROL_TIMERS
635     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEJacobian_un);
636   #endif
637   try {
638     // Get u_coeff from u and z_coeff from z
639     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff;
640     getCoeffFromStateVector(uo_coeff,uo);
641     getCoeffFromStateVector(un_coeff,un);
642     getCoeffFromControlVector(z_coeff,z);
643     // Initialize Jacobian matrices
644     if ( J == ROL::nullPtr ) {
645       J = ROL::makePtr<Tpetra::CrsMatrix<>>(matJ1Graph_);
646     }
647     // Assemble
648     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
649     pde->Jacobian_un(localVal,ts,uo_coeff,un_coeff,z_coeff,z_param);
650     assembleFieldMatrix( J, localVal, dofMgr1_, dofMgr1_ );
651     isJunTransposed_ = false;
652   }
653   catch ( Exception::Zero & ez ) {
654     throw Exception::Zero(">>> (Assembler::assembleDynPDEJacobian_un): Jacobian is zero.");
655   }
656   catch ( Exception::NotImplemented & eni ) {
657     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEJacobian_un): Jacobian not implemented.");
658   }
659 }
660 
661 template<class Real>
assembleDynPDEJacobian_zf(ROL::Ptr<Tpetra::CrsMatrix<>> & J,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)662 void Assembler<Real>::assembleDynPDEJacobian_zf(ROL::Ptr<Tpetra::CrsMatrix<>> &J,
663                                           const ROL::Ptr<DynamicPDE<Real>> &pde,
664                                           const ROL::TimeStamp<Real> &ts,
665                                           const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
666                                           const ROL::Ptr<const Tpetra::MultiVector<>> &un,
667                                           const ROL::Ptr<const Tpetra::MultiVector<>> &z,
668                                           const ROL::Ptr<const std::vector<Real>> &z_param) {
669   #ifdef ROL_TIMERS
670     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEJacobian_zf);
671   #endif
672   try {
673     // Get u_coeff from u and z_coeff from z
674     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff;
675     getCoeffFromStateVector(uo_coeff,uo);
676     getCoeffFromStateVector(un_coeff,un);
677     getCoeffFromControlVector(z_coeff,z);
678     // Initialize Jacobian matrices
679     if ( J == ROL::nullPtr ) {
680       J = ROL::makePtr<Tpetra::CrsMatrix<>>(matJ2Graph_);
681     }
682     // Assemble
683     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
684     pde->Jacobian_zf(localVal,ts,uo_coeff,un_coeff,z_coeff,z_param);
685     assembleFieldMatrix( J, localVal, dofMgr1_, dofMgr2_ );
686     isJzfTransposed_ = false;
687   }
688   catch ( Exception::Zero & ez ) {
689     throw Exception::Zero(">>> (Assembler::assembleDynPDEJacobian_zf): Jacobian is zero.");
690   }
691   catch ( Exception::NotImplemented & eni ) {
692     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEJacobian_zf): Jacobian not implemented.");
693   }
694 }
695 
696 template<class Real>
assembleDynPDEJacobian_zp(ROL::Ptr<Tpetra::MultiVector<>> & J,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)697 void Assembler<Real>::assembleDynPDEJacobian_zp(ROL::Ptr<Tpetra::MultiVector<>> &J,
698                                           const ROL::Ptr<DynamicPDE<Real>> &pde,
699                                           const ROL::TimeStamp<Real> &ts,
700                                           const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
701                                           const ROL::Ptr<const Tpetra::MultiVector<>> &un,
702                                           const ROL::Ptr<const Tpetra::MultiVector<>> &z,
703                                           const ROL::Ptr<const std::vector<Real>> & z_param) {
704   #ifdef ROL_TIMERS
705     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEJacobian_zp);
706   #endif
707   if ( z_param != ROL::nullPtr ) {
708     try {
709       int size = static_cast<int>(z_param->size());
710       // Get u_coeff from u and z_coeff from z
711       ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff;
712       getCoeffFromStateVector(uo_coeff,uo);
713       getCoeffFromStateVector(un_coeff,un);
714       getCoeffFromControlVector(z_coeff,z);
715       // Initialize Jacobian storage if not done so already
716       if (J == ROL::nullPtr) {
717         J = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueResidualMap_, size, true);
718       }
719       if ( pde_vecJ3_overlap_ == ROL::nullPtr) {
720         pde_vecJ3_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapResidualMap_, size, true);
721       }
722       // Assemble
723       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
724       pde->Jacobian_zp(localVal,ts,uo_coeff,un_coeff,z_coeff,z_param);
725       assembleParamFieldMatrix( J, localVal, pde_vecJ3_overlap_, dofMgr1_ );
726     }
727     catch ( Exception::Zero & ez ) {
728       throw Exception::Zero(">>> (Assembler::assembleDynPDEJacobian_zp): Jacobian is zero.");
729     }
730     catch ( Exception::NotImplemented & eni ) {
731       throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEJacobian_zp): Jacobian not implemented.");
732     }
733   }
734   else {
735     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEJacobian_zp): Jacobian not implemented.");
736   }
737 }
738 
739 template<class Real>
assembleDynPDEHessian_uo_uo(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)740 void Assembler<Real>::assembleDynPDEHessian_uo_uo(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
741                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
742                                             const ROL::TimeStamp<Real> &ts,
743                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
744                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
745                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
746                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
747                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
748   #ifdef ROL_TIMERS
749     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_uo_uo);
750   #endif
751   try {
752     // Get u_coeff from u and z_coeff from z
753     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
754     getCoeffFromStateVector(uo_coeff,uo);
755     getCoeffFromStateVector(un_coeff,un);
756     getCoeffFromControlVector(z_coeff,z);
757     getCoeffFromStateVector(l_coeff,l);
758     // Initialize Hessian storage if not done so already
759     if ( H == ROL::nullPtr ) {
760       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
761     }
762     // Assemble
763     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
764     pde->Hessian_uo_uo(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
765     assembleFieldMatrix( H, localVal, dofMgr1_, dofMgr1_ );
766   }
767   catch (Exception::Zero &ez) {
768     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_uo_uo): Hessian is zero.");
769   }
770   catch (Exception::NotImplemented &eni) {
771     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_uo_uo): Hessian not implemented.");
772   }
773 }
774 
775 template<class Real>
assembleDynPDEHessian_uo_un(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)776 void Assembler<Real>::assembleDynPDEHessian_uo_un(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
777                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
778                                             const ROL::TimeStamp<Real> &ts,
779                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
780                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
781                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
782                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
783                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
784   #ifdef ROL_TIMERS
785     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_uo_un);
786   #endif
787   try {
788     // Get u_coeff from u and z_coeff from z
789     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
790     getCoeffFromStateVector(uo_coeff,uo);
791     getCoeffFromStateVector(un_coeff,un);
792     getCoeffFromControlVector(z_coeff,z);
793     getCoeffFromStateVector(l_coeff,l);
794     // Initialize Hessian storage if not done so already
795     if ( H == ROL::nullPtr ) {
796       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
797     }
798     // Assemble
799     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
800     pde->Hessian_uo_un(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
801     assembleFieldMatrix( H, localVal, dofMgr1_, dofMgr1_ );
802   }
803   catch (Exception::Zero &ez) {
804     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_uo_un): Hessian is zero.");
805   }
806   catch (Exception::NotImplemented &eni) {
807     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_uo_un): Hessian not implemented.");
808   }
809 }
810 
811 template<class Real>
assembleDynPDEHessian_uo_zf(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)812 void Assembler<Real>::assembleDynPDEHessian_uo_zf(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
813                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
814                                             const ROL::TimeStamp<Real> &ts,
815                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
816                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
817                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
818                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
819                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
820   #ifdef ROL_TIMERS
821     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_uo_zf);
822   #endif
823   try {
824     // Get u_coeff from u and z_coeff from z
825     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
826     getCoeffFromStateVector(uo_coeff,uo);
827     getCoeffFromStateVector(un_coeff,un);
828     getCoeffFromControlVector(z_coeff,z);
829     getCoeffFromStateVector(l_coeff,l);
830     // Initialize Hessian storage if not done so already
831     if ( H == ROL::nullPtr ) {
832       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH12Graph_);
833     }
834     // Assemble
835     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
836     pde->Hessian_uo_zf(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
837     assembleFieldMatrix( H, localVal, dofMgr1_, dofMgr2_ );
838   }
839   catch (Exception::Zero &ez) {
840     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_uo_zf): Hessian is zero.");
841   }
842   catch (Exception::NotImplemented &eni) {
843     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_uo_zf): Hessian not implemented.");
844   }
845 }
846 
847 template<class Real>
assembleDynPDEHessian_uo_zp(ROL::Ptr<Tpetra::MultiVector<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)848 void Assembler<Real>::assembleDynPDEHessian_uo_zp(ROL::Ptr<Tpetra::MultiVector<>> &H,
849                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
850                                             const ROL::TimeStamp<Real> &ts,
851                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
852                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
853                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
854                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
855                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
856   #ifdef ROL_TIMERS
857     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_uo_zp);
858   #endif
859   if ( z_param != ROL::nullPtr ) {
860     try {
861       int size = static_cast<int>(z_param->size());
862       // Get u_coeff from u, z_coeff from z and l_coeff from l
863       ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
864       getCoeffFromStateVector(uo_coeff,uo);
865       getCoeffFromStateVector(un_coeff,un);
866       getCoeffFromControlVector(z_coeff,z);
867       getCoeffFromStateVector(l_coeff,l);
868       // Initialize Jacobian storage if not done so already
869       if (H == ROL::nullPtr) {
870         H = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, size, true);
871       }
872       if ( pde_vecH13_overlap_ == ROL::nullPtr) {
873         pde_vecH13_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, size, true);
874       }
875       // Assemble
876       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
877       pde->Hessian_uo_zp(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
878       assembleParamFieldMatrix( H, localVal, pde_vecH13_overlap_, dofMgr1_ );
879     }
880     catch ( Exception::Zero & ez ) {
881       throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_uo_zp): Hessian is zero.");
882     }
883     catch ( Exception::NotImplemented & eni ) {
884       throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_uo_zp): Hessian not implemented.");
885     }
886   }
887   else {
888     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_uo_zp): Hessian not implemented.");
889   }
890 }
891 
892 template<class Real>
assembleDynPDEHessian_un_uo(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)893 void Assembler<Real>::assembleDynPDEHessian_un_uo(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
894                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
895                                             const ROL::TimeStamp<Real> &ts,
896                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
897                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
898                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
899                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
900                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
901   #ifdef ROL_TIMERS
902     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_un_uo);
903   #endif
904   try {
905     // Get u_coeff from u and z_coeff from z
906     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
907     getCoeffFromStateVector(uo_coeff,uo);
908     getCoeffFromStateVector(un_coeff,un);
909     getCoeffFromControlVector(z_coeff,z);
910     getCoeffFromStateVector(l_coeff,l);
911     // Initialize Hessian storage if not done so already
912     if ( H == ROL::nullPtr ) {
913       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
914     }
915     // Assemble
916     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
917     pde->Hessian_un_uo(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
918     assembleFieldMatrix( H, localVal, dofMgr1_, dofMgr1_ );
919   }
920   catch (Exception::Zero &ez) {
921     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_un_uo): Hessian is zero.");
922   }
923   catch (Exception::NotImplemented &eni) {
924     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_un_uo): Hessian not implemented.");
925   }
926 }
927 
928 template<class Real>
assembleDynPDEHessian_un_un(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)929 void Assembler<Real>::assembleDynPDEHessian_un_un(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
930                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
931                                             const ROL::TimeStamp<Real> &ts,
932                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
933                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
934                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
935                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
936                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
937   #ifdef ROL_TIMERS
938     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_un_un);
939   #endif
940   try {
941     // Get u_coeff from u and z_coeff from z
942     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
943     getCoeffFromStateVector(uo_coeff,uo);
944     getCoeffFromStateVector(un_coeff,un);
945     getCoeffFromControlVector(z_coeff,z);
946     getCoeffFromStateVector(l_coeff,l);
947     // Initialize Hessian storage if not done so already
948     if ( H == ROL::nullPtr ) {
949       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
950     }
951     // Assemble
952     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
953     pde->Hessian_un_un(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
954     assembleFieldMatrix( H, localVal, dofMgr1_, dofMgr1_ );
955   }
956   catch (Exception::Zero &ez) {
957     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_un_un): Hessian is zero.");
958   }
959   catch (Exception::NotImplemented &eni) {
960     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_un_un): Hessian not implemented.");
961   }
962 }
963 
964 template<class Real>
assembleDynPDEHessian_un_zf(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)965 void Assembler<Real>::assembleDynPDEHessian_un_zf(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
966                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
967                                             const ROL::TimeStamp<Real> &ts,
968                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
969                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
970                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
971                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
972                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
973   #ifdef ROL_TIMERS
974     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_un_zf);
975   #endif
976   try {
977     // Get u_coeff from u and z_coeff from z
978     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
979     getCoeffFromStateVector(uo_coeff,uo);
980     getCoeffFromStateVector(un_coeff,un);
981     getCoeffFromControlVector(z_coeff,z);
982     getCoeffFromStateVector(l_coeff,l);
983     // Initialize Hessian storage if not done so already
984     if ( H == ROL::nullPtr ) {
985       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH12Graph_);
986     }
987     // Assemble
988     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
989     pde->Hessian_un_zf(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
990     assembleFieldMatrix( H, localVal, dofMgr1_, dofMgr2_ );
991   }
992   catch (Exception::Zero &ez) {
993     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_un_zf): Hessian is zero.");
994   }
995   catch (Exception::NotImplemented &eni) {
996     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_un_zf): Hessian not implemented.");
997   }
998 }
999 
1000 template<class Real>
assembleDynPDEHessian_un_zp(ROL::Ptr<Tpetra::MultiVector<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1001 void Assembler<Real>::assembleDynPDEHessian_un_zp(ROL::Ptr<Tpetra::MultiVector<>> &H,
1002                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1003                                             const ROL::TimeStamp<Real> &ts,
1004                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1005                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1006                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1007                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1008                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1009   #ifdef ROL_TIMERS
1010     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_un_zp);
1011   #endif
1012   if ( z_param != ROL::nullPtr ) {
1013     try {
1014       int size = static_cast<int>(z_param->size());
1015       // Get u_coeff from u, z_coeff from z and l_coeff from l
1016       ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
1017       getCoeffFromStateVector(uo_coeff,uo);
1018       getCoeffFromStateVector(un_coeff,un);
1019       getCoeffFromControlVector(z_coeff,z);
1020       getCoeffFromStateVector(l_coeff,l);
1021       // Initialize Jacobian storage if not done so already
1022       if (H == ROL::nullPtr) {
1023         H = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, size, true);
1024       }
1025       if ( pde_vecH13_overlap_ == ROL::nullPtr) {
1026         pde_vecH13_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, size, true);
1027       }
1028       // Assemble
1029       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
1030       pde->Hessian_un_zp(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
1031       assembleParamFieldMatrix( H, localVal, pde_vecH13_overlap_, dofMgr1_ );
1032     }
1033     catch ( Exception::Zero & ez ) {
1034       throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_un_zp): Hessian is zero.");
1035     }
1036     catch ( Exception::NotImplemented & eni ) {
1037       throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_un_zp): Hessian not implemented.");
1038     }
1039   }
1040   else {
1041     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_un_zp): Hessian not implemented.");
1042   }
1043 }
1044 
1045 template<class Real>
assembleDynPDEHessian_zf_uo(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1046 void Assembler<Real>::assembleDynPDEHessian_zf_uo(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
1047                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1048                                             const ROL::TimeStamp<Real> &ts,
1049                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1050                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1051                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1052                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1053                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1054   #ifdef ROL_TIMERS
1055     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zf_uo);
1056   #endif
1057   try {
1058     // Get u_coeff from u and z_coeff from z
1059     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
1060     getCoeffFromStateVector(uo_coeff,uo);
1061     getCoeffFromStateVector(un_coeff,un);
1062     getCoeffFromControlVector(z_coeff,z);
1063     getCoeffFromStateVector(l_coeff,l);
1064     // Initialize Hessian storage if not done so already
1065     if ( H == ROL::nullPtr ) {
1066       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH21Graph_);
1067     }
1068     // Assemble
1069     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1070     pde->Hessian_zf_uo(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
1071     assembleFieldMatrix( H, localVal, dofMgr2_, dofMgr1_ );
1072   }
1073   catch (Exception::Zero &ez) {
1074     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_zf_uo): Hessian is zero.");
1075   }
1076   catch (Exception::NotImplemented &eni) {
1077     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zf_uo): Hessian not implemented.");
1078   }
1079 }
1080 
1081 template<class Real>
assembleDynPDEHessian_zf_un(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1082 void Assembler<Real>::assembleDynPDEHessian_zf_un(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
1083                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1084                                             const ROL::TimeStamp<Real> &ts,
1085                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1086                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1087                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1088                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1089                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1090   #ifdef ROL_TIMERS
1091     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zf_un);
1092   #endif
1093   try {
1094     // Get u_coeff from u and z_coeff from z
1095     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
1096     getCoeffFromStateVector(uo_coeff,uo);
1097     getCoeffFromStateVector(un_coeff,un);
1098     getCoeffFromControlVector(z_coeff,z);
1099     getCoeffFromStateVector(l_coeff,l);
1100     // Initialize Hessian storage if not done so already
1101     if ( H == ROL::nullPtr ) {
1102       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH21Graph_);
1103     }
1104     // Assemble
1105     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1106     pde->Hessian_zf_un(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
1107     assembleFieldMatrix( H, localVal, dofMgr2_, dofMgr1_ );
1108   }
1109   catch (Exception::Zero &ez) {
1110     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_zf_un): Hessian is zero.");
1111   }
1112   catch (Exception::NotImplemented &eni) {
1113     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zf_un): Hessian not implemented.");
1114   }
1115 }
1116 
1117 template<class Real>
assembleDynPDEHessian_zf_zf(ROL::Ptr<Tpetra::CrsMatrix<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1118 void Assembler<Real>::assembleDynPDEHessian_zf_zf(ROL::Ptr<Tpetra::CrsMatrix<>> &H,
1119                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1120                                             const ROL::TimeStamp<Real> &ts,
1121                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1122                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1123                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1124                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1125                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1126   #ifdef ROL_TIMERS
1127     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zf_zf);
1128   #endif
1129   try {
1130     // Get u_coeff from u and z_coeff from z
1131     ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
1132     getCoeffFromStateVector(uo_coeff,uo);
1133     getCoeffFromStateVector(un_coeff,un);
1134     getCoeffFromControlVector(z_coeff,z);
1135     getCoeffFromStateVector(l_coeff,l);
1136     // Initialize Hessian storage if not done so already
1137     if ( H == ROL::nullPtr ) {
1138       H = ROL::makePtr<Tpetra::CrsMatrix<>>(matH22Graph_);
1139     }
1140     // Assemble
1141     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1142     pde->Hessian_zf_zf(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
1143     assembleFieldMatrix( H, localVal, dofMgr2_, dofMgr2_ );
1144   }
1145   catch (Exception::Zero &ez) {
1146     throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_zf_zf): Hessian is zero.");
1147   }
1148   catch (Exception::NotImplemented &eni) {
1149     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zf_zf): Hessian not implemented.");
1150   }
1151 }
1152 
1153 template<class Real>
assembleDynPDEHessian_zf_zp(ROL::Ptr<Tpetra::MultiVector<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1154 void Assembler<Real>::assembleDynPDEHessian_zf_zp(ROL::Ptr<Tpetra::MultiVector<>> &H,
1155                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1156                                             const ROL::TimeStamp<Real> &ts,
1157                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1158                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1159                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1160                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1161                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1162   #ifdef ROL_TIMERS
1163     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zf_zp);
1164   #endif
1165   if ( z_param != ROL::nullPtr ) {
1166     try {
1167       int size = static_cast<int>(z_param->size());
1168       // Get u_coeff from u, z_coeff from z and l_coeff from l
1169       ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
1170       getCoeffFromStateVector(uo_coeff,uo);
1171       getCoeffFromStateVector(un_coeff,un);
1172       getCoeffFromControlVector(z_coeff,z);
1173       getCoeffFromStateVector(l_coeff,l);
1174       // Initialize Jacobian storage if not done so already
1175       if (H == ROL::nullPtr) {
1176         H = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, size, true);
1177       }
1178       if ( pde_vecH23_overlap_ == ROL::nullPtr) {
1179         pde_vecH23_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, size, true);
1180       }
1181       // Assemble
1182       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
1183       pde->Hessian_zf_zp(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
1184       assembleParamFieldMatrix( H, localVal, pde_vecH23_overlap_, dofMgr2_ );
1185     }
1186     catch ( Exception::Zero & ez ) {
1187       throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_zf_zp): Hessian is zero.");
1188     }
1189     catch ( Exception::NotImplemented & eni ) {
1190       throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zf_zp): Hessian not implemented.");
1191     }
1192   }
1193   else {
1194     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zf_zp): Hessian not implemented.");
1195   }
1196 }
1197 
1198 template<class Real>
assembleDynPDEHessian_zp_uo(ROL::Ptr<Tpetra::MultiVector<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1199 void Assembler<Real>::assembleDynPDEHessian_zp_uo(ROL::Ptr<Tpetra::MultiVector<>> &H,
1200                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1201                                             const ROL::TimeStamp<Real> &ts,
1202                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1203                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1204                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1205                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1206                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1207   #ifdef ROL_TIMERS
1208     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zp_uo);
1209   #endif
1210   assembleDynPDEHessian_uo_zp(H,pde,ts,l,uo,un,z,z_param);
1211 }
1212 
1213 template<class Real>
assembleDynPDEHessian_zp_un(ROL::Ptr<Tpetra::MultiVector<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1214 void Assembler<Real>::assembleDynPDEHessian_zp_un(ROL::Ptr<Tpetra::MultiVector<>> &H,
1215                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1216                                             const ROL::TimeStamp<Real> &ts,
1217                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1218                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1219                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1220                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1221                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1222   #ifdef ROL_TIMERS
1223     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zp_un);
1224   #endif
1225   assembleDynPDEHessian_un_zp(H,pde,ts,l,uo,un,z,z_param);
1226 }
1227 
1228 template<class Real>
assembleDynPDEHessian_zp_zf(ROL::Ptr<Tpetra::MultiVector<>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1229 void Assembler<Real>::assembleDynPDEHessian_zp_zf(ROL::Ptr<Tpetra::MultiVector<>> &H,
1230                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1231                                             const ROL::TimeStamp<Real> &ts,
1232                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1233                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1234                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1235                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1236                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1237   #ifdef ROL_TIMERS
1238     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zp_zf);
1239   #endif
1240   assembleDynPDEHessian_zf_zp(H,pde,ts,l,uo,un,z,z_param);
1241 }
1242 
1243 template<class Real>
assembleDynPDEHessian_zp_zp(ROL::Ptr<std::vector<std::vector<Real>>> & H,const ROL::Ptr<DynamicPDE<Real>> & pde,const ROL::TimeStamp<Real> & ts,const ROL::Ptr<const Tpetra::MultiVector<>> & l,const ROL::Ptr<const Tpetra::MultiVector<>> & uo,const ROL::Ptr<const Tpetra::MultiVector<>> & un,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1244 void Assembler<Real>::assembleDynPDEHessian_zp_zp(ROL::Ptr<std::vector<std::vector<Real>>> &H,
1245                                             const ROL::Ptr<DynamicPDE<Real>> &pde,
1246                                             const ROL::TimeStamp<Real> &ts,
1247                                             const ROL::Ptr<const Tpetra::MultiVector<>> &l,
1248                                             const ROL::Ptr<const Tpetra::MultiVector<>> &uo,
1249                                             const ROL::Ptr<const Tpetra::MultiVector<>> &un,
1250                                             const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1251                                             const ROL::Ptr<const std::vector<Real>> & z_param) {
1252   #ifdef ROL_TIMERS
1253     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleDynPDEHessian_zp_zp);
1254   #endif
1255   if ( z_param != ROL::nullPtr ) {
1256     try {
1257       int size = static_cast<int>(z_param->size());
1258       // Get u_coeff from u, z_coeff from z and l_coeff from l
1259       ROL::Ptr<Intrepid::FieldContainer<Real>> uo_coeff, un_coeff, z_coeff, l_coeff;
1260       getCoeffFromStateVector(uo_coeff,uo);
1261       getCoeffFromStateVector(un_coeff,un);
1262       getCoeffFromControlVector(z_coeff,z);
1263       getCoeffFromStateVector(l_coeff,l);
1264       // Initialize Jacobian storage if not done so already
1265       if (H == ROL::nullPtr) {
1266         std::vector<Real> col(size,static_cast<Real>(0));
1267         H = ROL::makePtr<std::vector<std::vector<Real>>>(size,col);
1268       }
1269       // Assemble
1270       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> tmp(size,ROL::nullPtr);
1271       std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> localVal(size,tmp);
1272       pde->Hessian_zp_zp(localVal,ts,l_coeff,uo_coeff,un_coeff,z_coeff,z_param);
1273       assembleParamMatrix( H, localVal, dofMgr1_ );
1274     }
1275     catch ( Exception::Zero & ez ) {
1276       throw Exception::Zero(">>> (Assembler::assembleDynPDEHessian_zp_zp): Hessian is zero.");
1277     }
1278     catch ( Exception::NotImplemented & eni ) {
1279       throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zp_zp): Hessian not implemented.");
1280     }
1281   }
1282   else {
1283     throw Exception::NotImplemented(">>> (Assembler::assembleDynPDEHessian_zp_zp): Hessian not implemented.");
1284   }
1285 }
1286 /***************************************************************************/
1287 /* End of PDE assembly routines.                                           */
1288 /***************************************************************************/
1289 
1290 /***************************************************************************/
1291 /* QoI assembly routines                                                   */
1292 /***************************************************************************/
1293 template<class Real>
assembleQoIValue(const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1294 Real Assembler<Real>::assembleQoIValue(const ROL::Ptr<QoI<Real>> &qoi,
1295                                        const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1296                                        const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1297                                        const ROL::Ptr<const std::vector<Real>> & z_param) {
1298   #ifdef ROL_TIMERS
1299     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIValue);
1300   #endif
1301   Real val(0);
1302   try {
1303     // Get u_coeff from u and z_coeff from z
1304     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1305     getCoeffFromStateVector(u_coeff,u);
1306     getCoeffFromControlVector(z_coeff,z);
1307     // Assemble
1308     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1309     val  = qoi->value(localVal,u_coeff,z_coeff,z_param);
1310     val += assembleScalar( localVal );
1311   }
1312   catch ( Exception::Zero & ez ) {
1313     val = static_cast<Real>(0);
1314   }
1315   catch ( Exception::NotImplemented & eni ) {
1316     throw Exception::NotImplemented(">>> (Assembler::assembleQoIValue): Value not implemented.");
1317   }
1318   return val;
1319 }
1320 
1321 template<class Real>
assembleQoIGradient1(ROL::Ptr<Tpetra::MultiVector<>> & g1,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1322 void Assembler<Real>::assembleQoIGradient1(ROL::Ptr<Tpetra::MultiVector<>> &g1,
1323                                      const ROL::Ptr<QoI<Real>> &qoi,
1324                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1325                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1326                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1327   #ifdef ROL_TIMERS
1328     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIGradient1);
1329   #endif
1330   try {
1331     // Initialize state QoI gradient vectors
1332     if ( g1 == ROL::nullPtr ) {
1333       g1 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, 1, true);
1334     }
1335     if ( qoi_vecG1_overlap_ == ROL::nullPtr ) {
1336       qoi_vecG1_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, 1, true);
1337     }
1338     // Get u_coeff from u and z_coeff from z
1339     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1340     getCoeffFromStateVector(u_coeff,u);
1341     getCoeffFromControlVector(z_coeff,z);
1342     // Assemble
1343     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1344     qoi->gradient_1(localVal,u_coeff,z_coeff,z_param);
1345     assembleFieldVector( g1, localVal, qoi_vecG1_overlap_, dofMgr1_ );
1346   }
1347   catch ( Exception::Zero & ez ) {
1348     throw Exception::Zero(">>> (Assembler::assembleQoIGradient1): Gradient is zero.");
1349   }
1350   catch ( Exception::NotImplemented & eni ) {
1351     throw Exception::NotImplemented(">>> (Assembler::assembleQoIGradient1): Gradient not implemented.");
1352   }
1353 }
1354 
1355 template<class Real>
assembleQoIGradient2(ROL::Ptr<Tpetra::MultiVector<>> & g2,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1356 void Assembler<Real>::assembleQoIGradient2(ROL::Ptr<Tpetra::MultiVector<>> &g2,
1357                                      const ROL::Ptr<QoI<Real>> &qoi,
1358                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1359                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1360                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1361   #ifdef ROL_TIMERS
1362     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIGradient2);
1363   #endif
1364   try {
1365     // Initialize control gradient vectors
1366     if ( g2 == ROL::nullPtr ) {
1367       g2 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, 1, true);
1368     }
1369     if ( qoi_vecG2_overlap_ == ROL::nullPtr ) {
1370       qoi_vecG2_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, 1, true);
1371     }
1372     // Get u_coeff from u and z_coeff from z
1373     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1374     getCoeffFromStateVector(u_coeff,u);
1375     getCoeffFromControlVector(z_coeff,z);
1376     // Assemble
1377     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1378     qoi->gradient_2(localVal,u_coeff,z_coeff,z_param);
1379     assembleFieldVector( g2, localVal, qoi_vecG2_overlap_, dofMgr2_ );
1380   }
1381   catch ( Exception::Zero & ez ) {
1382     throw Exception::Zero(">>> (Assembler::assembleQoIGradient2): Gradient is zero.");
1383   }
1384   catch ( Exception::NotImplemented & eni ) {
1385     throw Exception::NotImplemented(">>> (Assembler::assembleQoIGradient2): Gradient not implemented.");
1386   }
1387 }
1388 
1389 template<class Real>
assembleQoIGradient3(ROL::Ptr<std::vector<Real>> & g3,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1390 void Assembler<Real>::assembleQoIGradient3(ROL::Ptr<std::vector<Real>> &g3,
1391                                      const ROL::Ptr<QoI<Real>> &qoi,
1392                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1393                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1394                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1395   #ifdef ROL_TIMERS
1396     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIGradient3);
1397   #endif
1398   if ( z_param != ROL::nullPtr ) {
1399     const int size = z_param->size();
1400     if ( g3 == ROL::nullPtr ) {
1401       g3 = ROL::makePtr<std::vector<Real>>(size,0);
1402     }
1403     try {
1404       // Get u_coeff from u and z_coeff from z
1405       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1406       getCoeffFromStateVector(u_coeff,u);
1407       getCoeffFromControlVector(z_coeff,z);
1408       // Assemble
1409       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
1410       std::vector<Real> g = qoi->gradient_3(localVal,u_coeff,z_coeff,z_param);
1411       assembleParamVector( g3, localVal );
1412       for (int i = 0; i < size; ++i) {
1413         (*g3)[i] += g[i];
1414       }
1415     }
1416     catch ( Exception::Zero & ez ) {
1417       g3->assign(size,0);
1418     }
1419     catch ( Exception::NotImplemented & eni ) {
1420       throw Exception::NotImplemented(">>> (Assembler::assembleQoIGradient3): Gradient not implemented.");
1421     }
1422   }
1423   else {
1424     throw Exception::NotImplemented(">>> (Assembler::assembleQoIGradient3): Gradient not implemented.");
1425   }
1426 }
1427 
1428 template<class Real>
assembleQoIHessVec11(ROL::Ptr<Tpetra::MultiVector<>> & H11,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1429 void Assembler<Real>::assembleQoIHessVec11(ROL::Ptr<Tpetra::MultiVector<>> &H11,
1430                                      const ROL::Ptr<QoI<Real>> &qoi,
1431                                      const ROL::Ptr<const Tpetra::MultiVector<>> &v,
1432                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1433                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1434                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1435   #ifdef ROL_TIMERS
1436     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec11);
1437   #endif
1438 	  try {
1439     // Get u_coeff from u and z_coeff from z
1440     ROL::Ptr<Intrepid::FieldContainer<Real>> v_coeff, u_coeff, z_coeff;
1441     getCoeffFromStateVector(v_coeff,v);
1442     getCoeffFromStateVector(u_coeff,u);
1443     getCoeffFromControlVector(z_coeff,z);
1444     // Initialize state-state HessVec vectors
1445     if ( H11 == ROL::nullPtr ) {
1446       H11 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, 1, true);
1447     }
1448     if ( qoi_vecH11_overlap_ == ROL::nullPtr ) {
1449       qoi_vecH11_overlap_  = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, 1, true);
1450     }
1451     // Assemble
1452     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1453     qoi->HessVec_11(localVal,v_coeff,u_coeff,z_coeff,z_param);
1454     assembleFieldVector( H11, localVal, qoi_vecH11_overlap_, dofMgr1_ );
1455   }
1456   catch (Exception::Zero &ez) {
1457     throw Exception::Zero(">>> (Assembler::assembleQoIHessVec11): Hessian is zero.");
1458   }
1459   catch (Exception::NotImplemented &eni) {
1460     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec11): Hessian not implemented.");
1461   }
1462 }
1463 
1464 template<class Real>
assembleQoIHessVec12(ROL::Ptr<Tpetra::MultiVector<>> & H12,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1465 void Assembler<Real>::assembleQoIHessVec12(ROL::Ptr<Tpetra::MultiVector<>> &H12,
1466                                      const ROL::Ptr<QoI<Real>> &qoi,
1467                                      const ROL::Ptr<const Tpetra::MultiVector<>> &v,
1468                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1469                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1470                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1471   #ifdef ROL_TIMERS
1472     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec12);
1473   #endif
1474   try {
1475     // Get u_coeff from u and z_coeff from z
1476     ROL::Ptr<Intrepid::FieldContainer<Real>> v_coeff, u_coeff, z_coeff;
1477     getCoeffFromControlVector(v_coeff,v);
1478     getCoeffFromStateVector(u_coeff,u);
1479     getCoeffFromControlVector(z_coeff,z);
1480     // Initialize state-control HessVec vectors
1481     if ( H12 == ROL::nullPtr ) {
1482       H12 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, 1, true);
1483     }
1484     if ( qoi_vecH12_overlap_ == ROL::nullPtr ) {
1485       qoi_vecH12_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, 1, true);
1486     }
1487     // Assemble
1488     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1489     qoi->HessVec_12(localVal,v_coeff,u_coeff,z_coeff,z_param);
1490     assembleFieldVector( H12, localVal, qoi_vecH12_overlap_, dofMgr1_ );
1491   }
1492   catch (Exception::Zero &ez) {
1493     throw Exception::Zero(">>> (Assembler::assembleQoIHessVec12): Hessian is zero.");
1494   }
1495   catch (Exception::NotImplemented &eni) {
1496     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec12): Hessian not implemented.");
1497   }
1498 }
1499 
1500 template<class Real>
assembleQoIHessVec13(ROL::Ptr<Tpetra::MultiVector<>> & H13,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const std::vector<Real>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1501 void Assembler<Real>::assembleQoIHessVec13(ROL::Ptr<Tpetra::MultiVector<>> &H13,
1502                                      const ROL::Ptr<QoI<Real>> &qoi,
1503                                      const ROL::Ptr<const std::vector<Real>> &v,
1504                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1505                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1506                                      const ROL::Ptr<const std::vector<Real>> &z_param) {
1507   #ifdef ROL_TIMERS
1508     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec13);
1509   #endif
1510   if (z_param != ROL::nullPtr) {
1511     try {
1512       // Get u_coeff from u and z_coeff from z
1513       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1514       getCoeffFromStateVector(u_coeff,u);
1515       getCoeffFromControlVector(z_coeff,z);
1516       // Initialize state-control HessVec vectors
1517       if ( H13 == ROL::nullPtr ) {
1518         H13 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, 1, true);
1519       }
1520       if ( qoi_vecH13_overlap_ == ROL::nullPtr ) {
1521         qoi_vecH13_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, 1, true);
1522       }
1523       // Assemble
1524       ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1525       qoi->HessVec_13(localVal,v,u_coeff,z_coeff,z_param);
1526       assembleFieldVector( H13, localVal, qoi_vecH13_overlap_, dofMgr1_ );
1527     }
1528     catch (Exception::Zero &ez) {
1529       throw Exception::Zero(">>> (Assembler::assembleQoIHessVec13): Hessian is zero.");
1530     }
1531     catch (Exception::NotImplemented &eni) {
1532       throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec13): Hessian not implemented.");
1533     }
1534   }
1535   else {
1536     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec13): Hessian not implemented.");
1537   }
1538 }
1539 
1540 template<class Real>
assembleQoIHessVec21(ROL::Ptr<Tpetra::MultiVector<>> & H21,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1541 void Assembler<Real>::assembleQoIHessVec21(ROL::Ptr<Tpetra::MultiVector<>> &H21,
1542                                      const ROL::Ptr<QoI<Real>> &qoi,
1543                                      const ROL::Ptr<const Tpetra::MultiVector<>> &v,
1544                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1545                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1546                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1547   #ifdef ROL_TIMERS
1548     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec21);
1549   #endif
1550   try {
1551     // Get u_coeff from u and z_coeff from z
1552     ROL::Ptr<Intrepid::FieldContainer<Real>> v_coeff, u_coeff, z_coeff;
1553     getCoeffFromStateVector(v_coeff,v);
1554     getCoeffFromStateVector(u_coeff,u);
1555     getCoeffFromControlVector(z_coeff,z);
1556     // Initialize control-state HessVec vectors
1557     if ( H21 == ROL::nullPtr ) {
1558       H21 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, 1, true);
1559     }
1560     if ( qoi_vecH21_overlap_ == ROL::nullPtr ) {
1561       qoi_vecH21_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, 1, true);
1562     }
1563     // Assemble
1564     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1565     qoi->HessVec_21(localVal,v_coeff,u_coeff,z_coeff,z_param);
1566     assembleFieldVector( H21, localVal, qoi_vecH21_overlap_, dofMgr2_ );
1567   }
1568   catch (Exception::Zero &ez) {
1569     throw Exception::Zero(">>> (Assembler::assembleQoIHessVec21): Hessian is zero.");
1570   }
1571   catch (Exception::NotImplemented &eni) {
1572     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec21): Hessian not implemented.");
1573   }
1574 }
1575 
1576 template<class Real>
assembleQoIHessVec22(ROL::Ptr<Tpetra::MultiVector<>> & H22,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1577 void Assembler<Real>::assembleQoIHessVec22(ROL::Ptr<Tpetra::MultiVector<>> &H22,
1578                                      const ROL::Ptr<QoI<Real>> &qoi,
1579                                      const ROL::Ptr<const Tpetra::MultiVector<>> &v,
1580                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1581                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1582                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1583   #ifdef ROL_TIMERS
1584     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec22);
1585   #endif
1586   try {
1587     // Get u_coeff from u and z_coeff from z
1588     ROL::Ptr<Intrepid::FieldContainer<Real>> v_coeff, u_coeff, z_coeff;
1589     getCoeffFromControlVector(v_coeff,v);
1590     getCoeffFromStateVector(u_coeff,u);
1591     getCoeffFromControlVector(z_coeff,z);
1592     // Initialize control-control HessVec vectors
1593     if ( H22 == ROL::nullPtr ) {
1594       H22 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, 1, true);
1595     }
1596     if ( qoi_vecH22_overlap_ == ROL::nullPtr ) {
1597       qoi_vecH22_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, 1, true);
1598     }
1599     // Assemble
1600     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1601     qoi->HessVec_22(localVal,v_coeff,u_coeff,z_coeff,z_param);
1602     assembleFieldVector( H22, localVal, qoi_vecH22_overlap_, dofMgr2_ );
1603   }
1604   catch (Exception::Zero &ez) {
1605     throw Exception::Zero(">>> (Assembler::assembleQoIHessVec22): Hessian is zero.");
1606   }
1607   catch (Exception::NotImplemented &eni) {
1608     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec22): Hessian not implemented.");
1609   }
1610 }
1611 
1612 template<class Real>
assembleQoIHessVec23(ROL::Ptr<Tpetra::MultiVector<>> & H23,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const std::vector<Real>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1613 void Assembler<Real>::assembleQoIHessVec23(ROL::Ptr<Tpetra::MultiVector<>> &H23,
1614                                      const ROL::Ptr<QoI<Real>> &qoi,
1615                                      const ROL::Ptr<const std::vector<Real>> &v,
1616                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1617                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1618                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1619   #ifdef ROL_TIMERS
1620     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec23);
1621   #endif
1622   if (z_param != ROL::nullPtr) {
1623     try {
1624       // Get u_coeff from u and z_coeff from z
1625       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1626       getCoeffFromStateVector(u_coeff,u);
1627       getCoeffFromControlVector(z_coeff,z);
1628       // Initialize control-control HessVec vectors
1629       if ( H23 == ROL::nullPtr ) {
1630         H23 = ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, 1, true);
1631       }
1632       if ( qoi_vecH23_overlap_ == ROL::nullPtr ) {
1633         qoi_vecH23_overlap_ = ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, 1, true);
1634       }
1635       // Assemble
1636       ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1637       qoi->HessVec_23(localVal,v,u_coeff,z_coeff,z_param);
1638       assembleFieldVector( H23, localVal, qoi_vecH23_overlap_, dofMgr2_ );
1639     }
1640     catch (Exception::Zero &ez) {
1641       throw Exception::Zero(">>> (Assembler::assembleQoIHessVec23): Hessian is zero.");
1642     }
1643     catch (Exception::NotImplemented &eni) {
1644       throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec23): Hessian not implemented.");
1645     }
1646   }
1647   else {
1648     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec23): Hessian not implemented.");
1649   }
1650 
1651 }
1652 
1653 template<class Real>
assembleQoIHessVec31(ROL::Ptr<std::vector<Real>> & H31,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1654 void Assembler<Real>::assembleQoIHessVec31(ROL::Ptr<std::vector<Real>> &H31,
1655                                      const ROL::Ptr<QoI<Real>> &qoi,
1656                                      const ROL::Ptr<const Tpetra::MultiVector<>> &v,
1657                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1658                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1659                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1660   #ifdef ROL_TIMERS
1661     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec31);
1662   #endif
1663   if ( z_param != ROL::nullPtr ) {
1664     const int size = z_param->size();
1665     if ( H31 == ROL::nullPtr ) {
1666       H31 = ROL::makePtr<std::vector<Real>>(size,0);
1667     }
1668     try {
1669       H31->assign(size,0);
1670       // Get u_coeff from u and z_coeff from z
1671       ROL::Ptr<Intrepid::FieldContainer<Real>> v_coeff, u_coeff, z_coeff;
1672       getCoeffFromStateVector(v_coeff,v);
1673       getCoeffFromStateVector(u_coeff,u);
1674       getCoeffFromControlVector(z_coeff,z);
1675       // Assemble
1676       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
1677       std::vector<Real> H = qoi->HessVec_31(localVal,v_coeff,u_coeff,z_coeff,z_param);
1678       assembleParamVector( H31, localVal );
1679       for (int i = 0; i < size; ++i) {
1680         (*H31)[i] += H[i];
1681       }
1682     }
1683     catch ( Exception::Zero & ez ) {
1684       H31->assign(size,0);
1685     }
1686     catch ( Exception::NotImplemented & eni ) {
1687       throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec31): HessVec not implemented.");
1688     }
1689   }
1690   else {
1691     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec31): HessVec not implemented.");
1692   }
1693 }
1694 
1695 template<class Real>
assembleQoIHessVec32(ROL::Ptr<std::vector<Real>> & H32,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1696 void Assembler<Real>::assembleQoIHessVec32(ROL::Ptr<std::vector<Real>> &H32,
1697                                      const ROL::Ptr<QoI<Real>> &qoi,
1698                                      const ROL::Ptr<const Tpetra::MultiVector<>> &v,
1699                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1700                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1701                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1702   #ifdef ROL_TIMERS
1703     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec32);
1704   #endif
1705   if ( z_param != ROL::nullPtr ) {
1706     const int size = z_param->size();
1707     if ( H32 == ROL::nullPtr ) {
1708       H32 = ROL::makePtr<std::vector<Real>>(size,0);
1709     }
1710     try {
1711       H32->assign(size,0);
1712       // Get u_coeff from u and z_coeff from z
1713       ROL::Ptr<Intrepid::FieldContainer<Real>> v_coeff, u_coeff, z_coeff;
1714       getCoeffFromControlVector(v_coeff,v);
1715       getCoeffFromStateVector(u_coeff,u);
1716       getCoeffFromControlVector(z_coeff,z);
1717       // Assemble
1718       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
1719       std::vector<Real> H = qoi->HessVec_32(localVal,v_coeff,u_coeff,z_coeff,z_param);
1720       assembleParamVector( H32, localVal );
1721       for (int i = 0; i < size; ++i) {
1722         (*H32)[i] += H[i];
1723       }
1724     }
1725     catch ( Exception::Zero & ez ) {
1726       H32->assign(size,0);
1727     }
1728     catch ( Exception::NotImplemented & eni ) {
1729       throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec32): HessVec not implemented.");
1730     }
1731   }
1732   else {
1733     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec32): HessVec not implemented.");
1734   }
1735 }
1736 
1737 template<class Real>
assembleQoIHessVec33(ROL::Ptr<std::vector<Real>> & H33,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const std::vector<Real>> & v,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1738 void Assembler<Real>::assembleQoIHessVec33(ROL::Ptr<std::vector<Real>> &H33,
1739                                      const ROL::Ptr<QoI<Real>> &qoi,
1740                                      const ROL::Ptr<const std::vector<Real>> &v,
1741                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1742                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1743                                      const ROL::Ptr<const std::vector<Real>> &z_param) {
1744   #ifdef ROL_TIMERS
1745     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessVec33);
1746   #endif
1747   if ( z_param != ROL::nullPtr ) {
1748     const int size = z_param->size();
1749     if ( H33 == ROL::nullPtr ) {
1750       H33 = ROL::makePtr<std::vector<Real>>(size,0);
1751     }
1752     try {
1753       H33->assign(size,0);
1754       // Get u_coeff from u and z_coeff from z
1755       ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1756       getCoeffFromStateVector(u_coeff,u);
1757       getCoeffFromControlVector(z_coeff,z);
1758       // Assemble
1759       std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> localVal(size,ROL::nullPtr);
1760       std::vector<Real> H = qoi->HessVec_33(localVal,v,u_coeff,z_coeff,z_param);
1761       assembleParamVector( H33, localVal );
1762       for (int i = 0; i < size; ++i) {
1763         (*H33)[i] += H[i];
1764       }
1765     }
1766     catch ( Exception::Zero & ez ) {
1767       H33->assign(size,0);
1768     }
1769     catch ( Exception::NotImplemented & eni ) {
1770       throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec33): HessVec not implemented.");
1771     }
1772   }
1773   else {
1774     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessVec33): HessVec not implemented.");
1775   }
1776 }
1777 
1778 template<class Real>
assembleQoIHessian11(ROL::Ptr<Tpetra::CrsMatrix<>> & H11,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1779 void Assembler<Real>::assembleQoIHessian11(ROL::Ptr<Tpetra::CrsMatrix<>> &H11,
1780                                      const ROL::Ptr<QoI<Real>> &qoi,
1781                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1782                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1783                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1784   #ifdef ROL_TIMERS
1785     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessian11);
1786   #endif
1787   try {
1788     // Get u_coeff from u and z_coeff from z
1789     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1790     getCoeffFromStateVector(u_coeff,u);
1791     getCoeffFromControlVector(z_coeff,z);
1792     // Initialize Jacobian matrices
1793     if ( H11 == ROL::nullPtr ) {
1794       H11 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
1795     }
1796     // Assemble
1797     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1798     qoi->Hessian_11(localVal,u_coeff,z_coeff,z_param);
1799     assembleFieldMatrix( H11, localVal, dofMgr1_, dofMgr1_ );
1800   }
1801   catch ( Exception::Zero & ez ) {
1802     throw Exception::Zero(">>> (Assembler::assembleQoIHessian11): Hessian is zero.");
1803   }
1804   catch ( Exception::NotImplemented & eni ) {
1805     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessian11): Hessian not implemented.");
1806   }
1807 }
1808 
1809 template<class Real>
assembleQoIHessian12(ROL::Ptr<Tpetra::CrsMatrix<>> & H12,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1810 void Assembler<Real>::assembleQoIHessian12(ROL::Ptr<Tpetra::CrsMatrix<>> &H12,
1811                                      const ROL::Ptr<QoI<Real>> &qoi,
1812                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1813                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1814                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1815   #ifdef ROL_TIMERS
1816     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessian12);
1817   #endif
1818   try {
1819     // Get u_coeff from u and z_coeff from z
1820     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1821     getCoeffFromStateVector(u_coeff,u);
1822     getCoeffFromControlVector(z_coeff,z);
1823     // Initialize Jacobian matrices
1824     if ( H12 == ROL::nullPtr ) {
1825       H12 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH12Graph_);
1826     }
1827     // Assemble
1828     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1829     qoi->Hessian_12(localVal,u_coeff,z_coeff,z_param);
1830     assembleFieldMatrix( H12, localVal, dofMgr1_, dofMgr2_ );
1831   }
1832   catch ( Exception::Zero & ez ) {
1833     throw Exception::Zero(">>> (Assembler::assembleQoIHessian12): Hessian is zero.");
1834   }
1835   catch ( Exception::NotImplemented & eni ) {
1836     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessian12): Hessian not implemented.");
1837   }
1838 }
1839 
1840 template<class Real>
assembleQoIHessian21(ROL::Ptr<Tpetra::CrsMatrix<>> & H21,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1841 void Assembler<Real>::assembleQoIHessian21(ROL::Ptr<Tpetra::CrsMatrix<>> &H21,
1842                                      const ROL::Ptr<QoI<Real>> &qoi,
1843                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1844                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1845                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1846   #ifdef ROL_TIMERS
1847     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessian21);
1848   #endif
1849   try {
1850     // Get u_coeff from u and z_coeff from z
1851     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1852     getCoeffFromStateVector(u_coeff,u);
1853     getCoeffFromControlVector(z_coeff,z);
1854     // Initialize Jacobian matrices
1855     if ( H21 == ROL::nullPtr ) {
1856       H21 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH21Graph_);
1857     }
1858     // Assemble
1859     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1860     qoi->Hessian_21(localVal,u_coeff,z_coeff,z_param);
1861     assembleFieldMatrix( H21, localVal, dofMgr2_, dofMgr1_ );
1862   }
1863   catch ( Exception::Zero & ez ) {
1864     throw Exception::Zero(">>> (Assembler::assembleQoIHessian21): Hessian is zero.");
1865   }
1866   catch ( Exception::NotImplemented & eni ) {
1867     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessian21): Hessian not implemented.");
1868   }
1869 }
1870 
1871 template<class Real>
assembleQoIHessian22(ROL::Ptr<Tpetra::CrsMatrix<>> & H22,const ROL::Ptr<QoI<Real>> & qoi,const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<const Tpetra::MultiVector<>> & z,const ROL::Ptr<const std::vector<Real>> & z_param)1872 void Assembler<Real>::assembleQoIHessian22(ROL::Ptr<Tpetra::CrsMatrix<>> &H22,
1873                                      const ROL::Ptr<QoI<Real>> &qoi,
1874                                      const ROL::Ptr<const Tpetra::MultiVector<>> &u,
1875                                      const ROL::Ptr<const Tpetra::MultiVector<>> &z,
1876                                      const ROL::Ptr<const std::vector<Real>> & z_param) {
1877   #ifdef ROL_TIMERS
1878     Teuchos::TimeMonitor LocalTimer(*ROL::PDEOPT::AssembleQOIHessian22);
1879   #endif
1880   try {
1881     // Get u_coeff from u and z_coeff from z
1882     ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff, z_coeff;
1883     getCoeffFromStateVector(u_coeff,u);
1884     getCoeffFromControlVector(z_coeff,z);
1885     // Initialize Jacobian matrices
1886     if ( H22 == ROL::nullPtr ) {
1887       H22 = ROL::makePtr<Tpetra::CrsMatrix<>>(matH11Graph_);
1888     }
1889     // Assemble
1890     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1891     qoi->Hessian_22(localVal,u_coeff,z_coeff,z_param);
1892     assembleFieldMatrix( H22, localVal, dofMgr2_, dofMgr2_ );
1893   }
1894   catch ( Exception::Zero & ez ) {
1895     throw Exception::Zero(">>> (Assembler::assembleQoIHessian22): Hessian is zero.");
1896   }
1897   catch ( Exception::NotImplemented & eni ) {
1898     throw Exception::NotImplemented(">>> (Assembler::assembleQoIHessian22): Hessian not implemented.");
1899   }
1900 }
1901 /***************************************************************************/
1902 /* End QoI assembly routines                                               */
1903 /***************************************************************************/
1904 
1905 /***************************************************************************/
1906 /* Assemble and apply Riesz operator corresponding to simulation variables */
1907 /***************************************************************************/
1908 template<class Real>
assemblePDERieszMap1(ROL::Ptr<Tpetra::CrsMatrix<>> & R1,const ROL::Ptr<PDE<Real>> & pde)1909 void Assembler<Real>::assemblePDERieszMap1(ROL::Ptr<Tpetra::CrsMatrix<>> &R1,
1910                                      const ROL::Ptr<PDE<Real>> &pde) {
1911   try {
1912     // Initialize Riesz matrix if not done so already
1913     if ( R1 == ROL::nullPtr ) {
1914     R1 = ROL::makePtr<Tpetra::CrsMatrix<>>(matR1Graph_);
1915     }
1916     // Assemble
1917     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1918     pde->RieszMap_1(localVal);
1919     assembleFieldMatrix( R1, localVal, dofMgr1_, dofMgr1_ );
1920   }
1921   catch ( Exception::NotImplemented & eni ) {
1922     //throw Exception::NotImplemented(">>> (Assembler::assemblePDERieszMap1): Riesz map not implemented!");
1923   }
1924   catch ( Exception::Zero & ez ) {
1925     //throw Exception::Zero(">>> (Assembler::assemblePDERieszMap1): Riesz map is zero!");
1926   }
1927 }
1928 template<class Real>
assembleDynPDERieszMap1(ROL::Ptr<Tpetra::CrsMatrix<>> & R1,const ROL::Ptr<DynamicPDE<Real>> & pde)1929 void Assembler<Real>::assembleDynPDERieszMap1(ROL::Ptr<Tpetra::CrsMatrix<>> &R1,
1930                                         const ROL::Ptr<DynamicPDE<Real>> &pde) {
1931   try {
1932     // Initialize Riesz matrix if not done so already
1933     if ( R1 == ROL::nullPtr ) {
1934     R1 = ROL::makePtr<Tpetra::CrsMatrix<>>(matR1Graph_);
1935     }
1936     // Assemble
1937     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1938     pde->RieszMap_1(localVal);
1939     assembleFieldMatrix( R1, localVal, dofMgr1_, dofMgr1_ );
1940   }
1941   catch ( Exception::NotImplemented & eni ) {
1942     //throw Exception::NotImplemented(">>> (Assembler::assemblePDERieszMap1): Riesz map not implemented!");
1943   }
1944   catch ( Exception::Zero & ez ) {
1945     //throw Exception::Zero(">>> (Assembler::assemblePDERieszMap1): Riesz map is zero!");
1946   }
1947 }
1948 /***************************************************************************/
1949 /* End of functions for Riesz operator of simulation variables.            */
1950 /***************************************************************************/
1951 
1952 /***************************************************************************/
1953 /* Assemble and apply Riesz operator corresponding to optimization         */
1954 /* variables                                                               */
1955 /***************************************************************************/
1956 template<class Real>
assemblePDERieszMap2(ROL::Ptr<Tpetra::CrsMatrix<>> & R2,const ROL::Ptr<PDE<Real>> & pde)1957 void Assembler<Real>::assemblePDERieszMap2(ROL::Ptr<Tpetra::CrsMatrix<>> &R2,
1958                                      const ROL::Ptr<PDE<Real>> &pde) {
1959   try {
1960     // Initialize Riesz matrix if not done so already
1961     if ( R2 == ROL::nullPtr ) {
1962       R2 = ROL::makePtr<Tpetra::CrsMatrix<>>(matR2Graph_);
1963     }
1964     // Assemble
1965     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1966     pde->RieszMap_2(localVal);
1967     assembleFieldMatrix( R2, localVal, dofMgr2_, dofMgr2_ );
1968   }
1969   catch ( Exception::NotImplemented & eni ) {
1970     //throw Exception::NotImplemented(">>> (Assembler::assemblePDERieszMap2): Riesz map not implemented!");
1971   }
1972   catch ( Exception::Zero & ez ) {
1973     //throw Exception::Zero(">>> (Assembler::assemblePDERieszMap2): Riesz map is zero!");
1974   }
1975 }
1976 template<class Real>
assembleDynPDERieszMap2(ROL::Ptr<Tpetra::CrsMatrix<>> & R2,const ROL::Ptr<DynamicPDE<Real>> & pde)1977 void Assembler<Real>::assembleDynPDERieszMap2(ROL::Ptr<Tpetra::CrsMatrix<>> &R2,
1978                                         const ROL::Ptr<DynamicPDE<Real>> &pde) {
1979   try {
1980     // Initialize Riesz matrix if not done so already
1981     if ( R2 == ROL::nullPtr ) {
1982       R2 = ROL::makePtr<Tpetra::CrsMatrix<>>(matR2Graph_);
1983     }
1984     // Assemble
1985     ROL::Ptr<Intrepid::FieldContainer<Real>> localVal;
1986     pde->RieszMap_2(localVal);
1987     assembleFieldMatrix( R2, localVal, dofMgr2_, dofMgr2_ );
1988   }
1989   catch ( Exception::NotImplemented & eni ) {
1990     //throw Exception::NotImplemented(">>> (Assembler::assemblePDERieszMap2): Riesz map not implemented!");
1991   }
1992   catch ( Exception::Zero & ez ) {
1993     //throw Exception::Zero(">>> (Assembler::assemblePDERieszMap2): Riesz map is zero!");
1994   }
1995 }
1996 /***************************************************************************/
1997 /* End of functions for Riesz operator of optimization variables.          */
1998 /***************************************************************************/
1999 
2000 /***************************************************************************/
2001 /* Compute error routines.                                                 */
2002 /***************************************************************************/
2003 template<class Real>
computeStateError(const ROL::Ptr<const Tpetra::MultiVector<>> & soln,const ROL::Ptr<Solution<Real>> & trueSoln,const int cubDeg,const ROL::Ptr<FieldHelper<Real>> & fieldHelper) const2004 Real Assembler<Real>::computeStateError(const ROL::Ptr<const Tpetra::MultiVector<>> &soln,
2005                                        const ROL::Ptr<Solution<Real>> &trueSoln,
2006                                        const int cubDeg,
2007                                        const ROL::Ptr<FieldHelper<Real>> &fieldHelper) const {
2008   Real totalError(0);
2009   // populate inCoeffs
2010   ROL::Ptr<Intrepid::FieldContainer<Real>> inCoeffs0;
2011   getCoeffFromStateVector(inCoeffs0, soln);
2012   // split fields
2013   int numFields = 1;
2014   std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> inCoeffs;
2015   if (fieldHelper != ROL::nullPtr) {
2016     numFields = fieldHelper->numFields();
2017     fieldHelper->splitFieldCoeff(inCoeffs,inCoeffs0);
2018   }
2019   else {
2020     inCoeffs.push_back(inCoeffs0);
2021   }
2022   // compute error
2023   for (int fn = 0; fn < numFields; ++fn) {
2024     // create fe object for error computation
2025     Intrepid::DefaultCubatureFactory<Real> cubFactory;
2026     shards::CellTopology cellType = basisPtrs1_[fn]->getBaseCellTopology();
2027     ROL::Ptr<Intrepid::Cubature<Real>> cellCub = cubFactory.create(cellType, cubDeg);
2028     ROL::Ptr<FE<Real>> fe
2029       = ROL::makePtr<FE<Real>>(volCellNodes_,basisPtrs1_[fn],cellCub);
2030 
2031     // get dimensions
2032     int c = fe->gradN()->dimension(0);
2033     int p = fe->gradN()->dimension(2);
2034     int d = fe->gradN()->dimension(3);
2035 
2036     // evaluate input coefficients on fe basis
2037     ROL::Ptr<Intrepid::FieldContainer<Real>> funcVals
2038       = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
2039     fe->evaluateValue(funcVals, inCoeffs[fn]);
2040 
2041     // subtract off true solution
2042     std::vector<Real> x(d);
2043     for (int i=0; i<c; ++i) {
2044       for (int j=0; j<p; ++j) {
2045         for (int k=0; k<d; ++k) {
2046           x[k] = (*fe->cubPts())(i, j, k);
2047         }
2048         (*funcVals)(i, j) -= trueSoln->evaluate(x,fn);
2049       }
2050     }
2051 
2052     // compute norm squared of local error
2053     ROL::Ptr<Intrepid::FieldContainer<Real>> normSquaredError
2054       = ROL::makePtr<Intrepid::FieldContainer<Real>>(c);
2055     fe->computeIntegral(normSquaredError, funcVals, funcVals, false);
2056 
2057     Real localErrorSum(0);
2058     Real globalErrorSum(0);
2059     for (int i=0; i<numCells_; ++i) {
2060       localErrorSum += (*normSquaredError)(i);
2061     }
2062     Teuchos::reduceAll<int, Real>(*comm_, Teuchos::REDUCE_SUM, 1, &localErrorSum, &globalErrorSum);
2063     totalError += globalErrorSum;
2064   }
2065 
2066   return std::sqrt(totalError);
2067 }
2068 
2069 template<class Real>
computeControlError(const ROL::Ptr<const Tpetra::MultiVector<>> & soln,const ROL::Ptr<Solution<Real>> & trueSoln,const int cubDeg,const ROL::Ptr<FieldHelper<Real>> & fieldHelper) const2070 Real Assembler<Real>::computeControlError(const ROL::Ptr<const Tpetra::MultiVector<>> &soln,
2071                                           const ROL::Ptr<Solution<Real>> &trueSoln,
2072                                           const int cubDeg,
2073                                           const ROL::Ptr<FieldHelper<Real>> &fieldHelper) const {
2074   Real totalError(0);
2075   // populate inCoeffs
2076   ROL::Ptr<Intrepid::FieldContainer<Real>> inCoeffs0;
2077   getCoeffFromControlVector(inCoeffs0, soln);
2078   // split fields
2079   int numFields = 1;
2080   std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> inCoeffs;
2081   if (fieldHelper != ROL::nullPtr) {
2082     numFields = fieldHelper->numFields();
2083     fieldHelper->splitFieldCoeff(inCoeffs,inCoeffs0);
2084   }
2085   else {
2086     inCoeffs.push_back(inCoeffs0);
2087   }
2088   // compute error
2089   for (int fn = 0; fn < numFields; ++fn) {
2090     // create fe object for error computation
2091     Intrepid::DefaultCubatureFactory<Real> cubFactory;
2092     shards::CellTopology cellType = basisPtrs2_[fn]->getBaseCellTopology();
2093     ROL::Ptr<Intrepid::Cubature<Real>> cellCub = cubFactory.create(cellType, cubDeg);
2094     ROL::Ptr<FE<Real>> fe
2095       = ROL::makePtr<FE<Real>>(volCellNodes_,basisPtrs2_[fn],cellCub);
2096 
2097     // get dimensions
2098     int c = fe->gradN()->dimension(0);
2099     int p = fe->gradN()->dimension(2);
2100     int d = fe->gradN()->dimension(3);
2101 
2102     // evaluate input coefficients on fe basis
2103     ROL::Ptr<Intrepid::FieldContainer<Real>> funcVals
2104       = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
2105     fe->evaluateValue(funcVals, inCoeffs[fn]);
2106 
2107     // subtract off true solution
2108     std::vector<Real> x(d);
2109     for (int i=0; i<c; ++i) {
2110       for (int j=0; j<p; ++j) {
2111         for (int k=0; k<d; ++k) {
2112           x[k] = (*fe->cubPts())(i, j, k);
2113         }
2114         (*funcVals)(i, j) -= trueSoln->evaluate(x,fn);
2115       }
2116     }
2117 
2118     // compute norm squared of local error
2119     ROL::Ptr<Intrepid::FieldContainer<Real>> normSquaredError
2120       = ROL::makePtr<Intrepid::FieldContainer<Real>>(c);
2121     fe->computeIntegral(normSquaredError, funcVals, funcVals, false);
2122 
2123     Real localErrorSum(0);
2124     Real globalErrorSum(0);
2125     for (int i=0; i<numCells_; ++i) {
2126       localErrorSum += (*normSquaredError)(i);
2127     }
2128     Teuchos::reduceAll<int, Real>(*comm_, Teuchos::REDUCE_SUM, 1, &localErrorSum, &globalErrorSum);
2129     totalError += globalErrorSum;
2130   }
2131 
2132   return std::sqrt(totalError);
2133 }
2134 /***************************************************************************/
2135 /* End of compute solution routines.                                       */
2136 /***************************************************************************/
2137 
2138 /***************************************************************************/
2139 /* Output routines.                                                        */
2140 /***************************************************************************/
2141 template<class Real>
printMeshData(std::ostream & outStream) const2142 void Assembler<Real>::printMeshData(std::ostream &outStream) const {
2143   ROL::Ptr<Intrepid::FieldContainer<Real>> nodesPtr = meshMgr_->getNodes();
2144   ROL::Ptr<Intrepid::FieldContainer<int>>  cellToNodeMapPtr = meshMgr_->getCellToNodeMap();
2145   Intrepid::FieldContainer<Real>  &nodes = *nodesPtr;
2146   Intrepid::FieldContainer<int>   &cellToNodeMap = *cellToNodeMapPtr;
2147   if ( verbose_ && myRank_ == 0) {
2148     outStream << std::endl;
2149     outStream << "Number of nodes = " << meshMgr_->getNumNodes() << std::endl;
2150     outStream << "Number of cells = " << meshMgr_->getNumCells() << std::endl;
2151     outStream << "Number of edges = " << meshMgr_->getNumEdges() << std::endl;
2152   }
2153   // Print mesh to file.
2154   if ((myRank_ == 0)) {
2155     std::ofstream meshfile;
2156     meshfile.open("cell_to_node_quad.txt");
2157     for (int i=0; i<cellToNodeMap.dimension(0); ++i) {
2158       for (int j=0; j<cellToNodeMap.dimension(1); ++j) {
2159         meshfile << cellToNodeMap(i,j) << "  ";
2160       }
2161       meshfile << std::endl;
2162     }
2163     meshfile.close();
2164 
2165 //    meshfile.open("cell_to_node_tri.txt");
2166 //    for (int i=0; i<cellToNodeMap.dimension(0); ++i) {
2167 //      for (int j=0; j<3; ++j) {
2168 //        meshfile << cellToNodeMap(i,j) << "  ";
2169 //      }
2170 //      meshfile << std::endl;
2171 //      for (int j=2; j<5; ++j) {
2172 //        meshfile << cellToNodeMap(i,j%4) << "  ";
2173 //      }
2174 //      meshfile << std::endl;
2175 //    }
2176 //    meshfile.close();
2177 
2178     meshfile.open("nodes.txt");
2179     meshfile.precision(16);
2180     for (int i=0; i<nodes.dimension(0); ++i) {
2181       for (int j=0; j<nodes.dimension(1); ++j) {
2182         meshfile << std::scientific << nodes(i,j) << "  ";
2183       }
2184       meshfile << std::endl;
2185     }
2186     meshfile.close();
2187   }
2188 } // prinf function end
2189 
2190 template<class Real>
outputTpetraVector(const ROL::Ptr<const Tpetra::MultiVector<>> & vec,const std::string & filename) const2191 void Assembler<Real>::outputTpetraVector(const ROL::Ptr<const Tpetra::MultiVector<>> &vec,
2192                                          const std::string &filename) const {
2193   Tpetra::MatrixMarket::Writer< Tpetra::CrsMatrix<>> vecWriter;
2194   vecWriter.writeDenseFile(filename, vec);
2195   std::string mapfile = "map_" + filename;
2196   vecWriter.writeMapFile(mapfile, *(vec->getMap()));
2197 }
2198 
2199 template<class Real>
inputTpetraVector(ROL::Ptr<Tpetra::MultiVector<>> & vec,const std::string & filename) const2200 void Assembler<Real>::inputTpetraVector(ROL::Ptr<Tpetra::MultiVector<>> &vec,
2201                                         const std::string &filename) const {
2202   Tpetra::MatrixMarket::Reader< Tpetra::CrsMatrix<>> vecReader;
2203   auto map = vec->getMap();
2204   auto comm = map->getComm();
2205   auto vec_rcp = vecReader.readDenseFile(filename, comm, map);
2206   vec->scale(1.0, *vec_rcp);
2207 }
2208 
2209 template<class Real>
serialPrintStateEdgeField(const ROL::Ptr<const Tpetra::MultiVector<>> & u,const ROL::Ptr<FieldHelper<Real>> & fieldHelper,const std::string & filename,const ROL::Ptr<FE_CURL<Real>> & fe) const2210 void Assembler<Real>::serialPrintStateEdgeField(const ROL::Ptr<const Tpetra::MultiVector<>> &u,
2211                                                 const ROL::Ptr<FieldHelper<Real>> &fieldHelper,
2212                                                 const std::string &filename,
2213                                                 const ROL::Ptr<FE_CURL<Real>> &fe) const {
2214   const int c = fe->curlN()->dimension(0);
2215   const int f = fe->curlN()->dimension(1);
2216   const int p = 1, d = 3;
2217 
2218   ROL::Ptr<Intrepid::FieldContainer<Real>> u_coeff;
2219   getCoeffFromStateVector(u_coeff,u);
2220 
2221   std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> U;
2222   fieldHelper->splitFieldCoeff(U, u_coeff);
2223   int numFields = U.size();
2224 
2225   // Transform cell center to physical
2226   ROL::Ptr<Intrepid::FieldContainer<Real>> rx
2227     = ROL::makePtr<Intrepid::FieldContainer<Real>>(p,d);
2228   ROL::Ptr<Intrepid::FieldContainer<Real>> px
2229     = ROL::makePtr<Intrepid::FieldContainer<Real>>(c,p,d);
2230   fe->mapRefPointsToPhysical(px,rx);
2231   // Transform reference values into physical space.
2232   ROL::Ptr<Intrepid::FieldContainer<Real>> cellJac
2233     = ROL::makePtr<Intrepid::FieldContainer<Real>>(c,p,d,d);
2234   ROL::Ptr<Intrepid::FieldContainer<Real>> cellJacInv
2235     = ROL::makePtr<Intrepid::FieldContainer<Real>>(c,p,d,d);
2236   ROL::Ptr<shards::CellTopology> cellTopo
2237     = ROL::makePtr<shards::CellTopology>(basisPtrs1_[0]->getBaseCellTopology());
2238   ROL::Ptr<Intrepid::FieldContainer<Real>> valReference
2239     = ROL::makePtr<Intrepid::FieldContainer<Real>>(f,p,d);
2240   basisPtrs1_[0]->getValues(*valReference,*rx,Intrepid::OPERATOR_VALUE);
2241   ROL::Ptr<Intrepid::FieldContainer<Real>> valPhysical
2242     = ROL::makePtr<Intrepid::FieldContainer<Real>>(c,f,p,d);
2243   Intrepid::CellTools<Real>::setJacobian(*cellJac,*rx,*volCellNodes_,*cellTopo);
2244   Intrepid::CellTools<Real>::setJacobianInv(*cellJacInv, *cellJac);
2245   Intrepid::FunctionSpaceTools::HCURLtransformVALUE<Real>(*valPhysical,
2246                                                           *cellJacInv,
2247                                                           *valReference);
2248 
2249   std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> uval(numFields);
2250   for (int k = 0; k < numFields; ++k) {
2251     uval[k] = ROL::makePtr<Intrepid::FieldContainer<Real>>(c,p,d);
2252     Intrepid::FunctionSpaceTools::evaluate<Real>(*uval[k], *U[k], *valPhysical);
2253   }
2254   // Print
2255   std::ofstream file;
2256   file.open(filename);
2257   for (int i = 0; i < c; ++i) {
2258     file << std::scientific << std::setprecision(15);
2259     for (int j = 0; j < d; ++j) {
2260       file << std::setw(25) << (*px)(i,0,j);
2261     }
2262     for (int k = 0; k < numFields; ++k) {
2263       for (int j = 0; j < d; ++j) {
2264         file << std::setw(25) << (*uval[k])(i,0,j);
2265       }
2266     }
2267     file << std::endl;
2268   }
2269   file.close();
2270 }
2271 /***************************************************************************/
2272 /* End of output routines.                                                 */
2273 /***************************************************************************/
2274 
2275 /***************************************************************************/
2276 /* Vector generation routines.                                             */
2277 /***************************************************************************/
2278 template<class Real>
getStateMap(void) const2279 const ROL::Ptr<const Tpetra::Map<>> Assembler<Real>::getStateMap(void) const {
2280   return myUniqueStateMap_;
2281 }
2282 
2283 template<class Real>
getControlMap(void) const2284 const ROL::Ptr<const Tpetra::Map<>> Assembler<Real>::getControlMap(void) const {
2285   return myUniqueControlMap_;
2286 }
2287 
2288 template<class Real>
getResidualMap(void) const2289 const ROL::Ptr<const Tpetra::Map<>> Assembler<Real>::getResidualMap(void) const {
2290   return myUniqueResidualMap_;
2291 }
2292 
2293 template<class Real>
createStateVector(void) const2294 ROL::Ptr<Tpetra::MultiVector<>> Assembler<Real>::createStateVector(void) const {
2295   return ROL::makePtr<Tpetra::MultiVector<>>(myUniqueStateMap_, 1, true);
2296 }
2297 
2298 template<class Real>
createControlVector(void) const2299 ROL::Ptr<Tpetra::MultiVector<>> Assembler<Real>::createControlVector(void) const {
2300   return ROL::makePtr<Tpetra::MultiVector<>>(myUniqueControlMap_, 1, true);
2301 }
2302 
2303 template<class Real>
createResidualVector(void) const2304 ROL::Ptr<Tpetra::MultiVector<>> Assembler<Real>::createResidualVector(void) const {
2305   return ROL::makePtr<Tpetra::MultiVector<>>(myUniqueResidualMap_, 1, true);
2306 }
2307 /***************************************************************************/
2308 /* End of vector generation routines.                                      */
2309 /***************************************************************************/
2310 
2311 /***************************************************************************/
2312 /* Accessor routines.                                                      */
2313 /***************************************************************************/
2314 template<class Real>
getDofManager(void) const2315 const ROL::Ptr<DofManager<Real>> Assembler<Real>::getDofManager(void) const {
2316   return dofMgr1_;
2317 }
2318 template<class Real>
getDofManager2(void) const2319 const ROL::Ptr<DofManager<Real>> Assembler<Real>::getDofManager2(void) const {
2320   return dofMgr2_;
2321 }
2322 
2323 template<class Real>
getCellIds(void) const2324 Teuchos::Array<typename Tpetra::Map<>::global_ordinal_type> Assembler<Real>::getCellIds(void) const {
2325   return myCellIds_;
2326 }
2327 /***************************************************************************/
2328 /* End of accessor routines.                                               */
2329 /***************************************************************************/
2330 
2331 /*****************************************************************************/
2332 /******************* PRIVATE MEMBER FUNCTIONS ********************************/
2333 /*****************************************************************************/
2334 template<class Real>
setCommunicator(const ROL::Ptr<const Teuchos::Comm<int>> & comm,Teuchos::ParameterList & parlist,std::ostream & outStream)2335 void Assembler<Real>::setCommunicator(const ROL::Ptr<const Teuchos::Comm<int>> &comm,
2336                                       Teuchos::ParameterList &parlist,
2337                                       std::ostream &outStream) {
2338   comm_ = comm;
2339   // Get number of processors and my rank
2340   myRank_    = comm->getRank();
2341   numProcs_  = comm->getSize();
2342   // Parse parameter list
2343   verbose_ = parlist.sublist("PDE FEM").get("Verbose Output",false);
2344   if (verbose_ && myRank_==0 ) {
2345     outStream << "Initialized communicator. " << std::endl;
2346   }
2347   if (verbose_ && myRank_==0 ) {
2348     outStream << "Total number of processors: " << numProcs_ << std::endl;
2349   }
2350 }
2351 
2352 template<class Real>
setBasis(const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs1,const std::vector<ROL::Ptr<Intrepid::Basis<Real,Intrepid::FieldContainer<Real>>>> & basisPtrs2,Teuchos::ParameterList & parlist,std::ostream & outStream)2353 void Assembler<Real>::setBasis(
2354        const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs1,
2355        const std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> &basisPtrs2,
2356        Teuchos::ParameterList &parlist,
2357        std::ostream &outStream) {
2358   basisPtrs1_ = basisPtrs1;
2359   basisPtrs2_ = basisPtrs2;
2360   if (verbose_ && myRank_==0) {
2361     outStream << "Initialized PDE." << std::endl;
2362   }
2363 }
2364 
2365 template<class Real>
setDiscretization(Teuchos::ParameterList & parlist,const ROL::Ptr<MeshManager<Real>> & meshMgr,std::ostream & outStream)2366 void Assembler<Real>::setDiscretization(Teuchos::ParameterList &parlist,
2367                                   const ROL::Ptr<MeshManager<Real>> &meshMgr,
2368                                         std::ostream &outStream) {
2369   if ( meshMgr != ROL::nullPtr ) {
2370     // Use MeshManager object if supplied
2371     meshMgr_ = meshMgr;
2372   }
2373   else {
2374     // Otherwise construct MeshManager objective from parameter list
2375   }
2376   dofMgr1_ = ROL::makePtr<DofManager<Real>>(meshMgr_,basisPtrs1_);
2377   dofMgr2_ = ROL::makePtr<DofManager<Real>>(meshMgr_,basisPtrs2_);
2378   if (verbose_ && myRank_==0) {
2379     outStream << "Initialized discretization (MeshManager and DofManager)." << std::endl;
2380   }
2381 }
2382 
2383 template<class Real>
setParallelStructure(Teuchos::ParameterList & parlist,std::ostream & outStream)2384 void Assembler<Real>::setParallelStructure(Teuchos::ParameterList &parlist,
2385                                            std::ostream &outStream) {
2386   int cellSplit = parlist.sublist("Geometry").get<int>("Partition type");
2387   /****************************************************/
2388   /*** Build parallel communication infrastructure. ***/
2389   /****************************************************/
2390   // Partition the cells in the mesh.  We use a basic quasi-equinumerous partitioning,
2391   // where the remainder, if any, is assigned to the last processor.
2392   Teuchos::Array<GO> myGlobalIds1, myGlobalIds2;
2393   cellOffsets_.assign(numProcs_, 0);
2394   int totalNumCells = meshMgr_->getNumCells();
2395   int cellsPerProc  = totalNumCells / numProcs_;
2396   numCells_         = cellsPerProc;
2397   ROL::Ptr<std::vector<std::vector<int>>> procCellIds = meshMgr_->getProcCellIds();
2398   switch(cellSplit) {
2399     case 0:
2400       if (myRank_ == 0) {
2401         // remainder in the first
2402         numCells_ += totalNumCells % numProcs_;
2403       }
2404       for (int i=1; i<numProcs_; ++i) {
2405         cellOffsets_[i] = cellOffsets_[i-1] + cellsPerProc
2406                           + (static_cast<int>(i==1))*(totalNumCells % numProcs_);
2407       }
2408       break;
2409     case 1:
2410       if (myRank_ == numProcs_-1) {
2411         // remainder in the last
2412         numCells_ += totalNumCells % numProcs_;
2413       }
2414       for (int i=1; i<numProcs_; ++i) {
2415         cellOffsets_[i] = cellOffsets_[i-1] + cellsPerProc;
2416       }
2417       break;
2418     case 2:
2419       if (myRank_ < (totalNumCells%numProcs_)) {
2420         // spread remainder, starting from the first
2421         numCells_++;
2422       }
2423       for (int i=1; i<numProcs_; ++i) {
2424         cellOffsets_[i] = cellOffsets_[i-1] + cellsPerProc
2425                           + (static_cast<int>(i-1<(totalNumCells%numProcs_)));
2426       }
2427       break;
2428     case 3:
2429       // Define using MeshManager.
2430       numCells_ = (*procCellIds)[myRank_].size();
2431       break;
2432   }
2433 
2434   Intrepid::FieldContainer<int> &cellDofs1 = *(dofMgr1_->getCellDofs());
2435   Intrepid::FieldContainer<int> &cellDofs2 = *(dofMgr2_->getCellDofs());
2436   int numLocalDofs1 = cellDofs1.dimension(1);
2437   int numLocalDofs2 = cellDofs2.dimension(1);
2438   if (verbose_) {
2439     outStream << "Cell offsets across processors: " << cellOffsets_
2440               << std::endl;
2441   }
2442   switch(cellSplit) {
2443     case 0:
2444     case 1:
2445     case 2:
2446     for (int i=0; i<numCells_; ++i) {
2447       myCellIds_.push_back(cellOffsets_[myRank_]+i);
2448       for (int j=0; j<numLocalDofs1; ++j) {
2449         myGlobalIds1.push_back( cellDofs1(cellOffsets_[myRank_]+i,j) );
2450       }
2451       for (int j=0; j<numLocalDofs2; ++j) {
2452         myGlobalIds2.push_back( cellDofs2(cellOffsets_[myRank_]+i,j) );
2453       }
2454     }
2455       break;
2456     case 3:
2457     for (int i=0; i<numCells_; ++i) {
2458       myCellIds_.push_back((*procCellIds)[myRank_][i]);
2459       for (int j=0; j<numLocalDofs1; ++j) {
2460         myGlobalIds1.push_back( cellDofs1((*procCellIds)[myRank_][i],j) );
2461       }
2462       for (int j=0; j<numLocalDofs2; ++j) {
2463         myGlobalIds2.push_back( cellDofs2((*procCellIds)[myRank_][i],j) );
2464       }
2465     }
2466       break;
2467   }
2468   std::sort(myGlobalIds1.begin(), myGlobalIds1.end());
2469   myGlobalIds1.erase( std::unique(myGlobalIds1.begin(),myGlobalIds1.end()),myGlobalIds1.end() );
2470   std::sort(myGlobalIds2.begin(), myGlobalIds2.end());
2471   myGlobalIds2.erase( std::unique(myGlobalIds2.begin(),myGlobalIds2.end()),myGlobalIds2.end() );
2472 
2473   // Build maps.
2474   myOverlapStateMap_    = ROL::makePtr<Tpetra::Map<>>
2475     (Teuchos::OrdinalTraits<GO>::invalid(), myGlobalIds1, GO(0), comm_);
2476   //std::cout << std::endl << myOverlapMap_->getNodeElementList()<<std::endl;
2477   /** One can also use the non-member function:
2478       myOverlapMap_ = Tpetra::createNonContigMap<int,int>(myGlobalIds_, comm_);
2479       to build the overlap map.
2480   **/
2481   myUniqueStateMap_     = Tpetra::createOneToOne(myOverlapStateMap_);
2482   myOverlapResidualMap_ = myOverlapStateMap_;
2483   myUniqueResidualMap_  = myUniqueStateMap_;
2484   myOverlapControlMap_  = ROL::makePtr<Tpetra::Map<>>
2485      (Teuchos::OrdinalTraits<GO>::invalid(), myGlobalIds2, GO(0), comm_);
2486   myUniqueControlMap_   = Tpetra::createOneToOne(myOverlapControlMap_);;
2487   //std::cout << std::endl << myUniqueMap_->getNodeElementList() << std::endl;
2488   //  myCellMap_ = ROL::makePtr<Tpetra::Map<>>(
2489   //               Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid(),
2490   //               myCellIds_, 0, comm_);
2491 
2492   /****************************************/
2493   /*** Assemble global graph structure. ***/
2494   /****************************************/
2495 
2496   // Make a GO copy to interface with Tpetra; currently dof manager uses int directly
2497   Teuchos::ArrayRCP<const int> cellDofs1ArrayRCP = cellDofs1.getData();
2498   Teuchos::ArrayRCP<const int> cellDofs2ArrayRCP = cellDofs2.getData();
2499   Teuchos::ArrayRCP<GO> cellDofs1GO(cellDofs1ArrayRCP.size(), GO());
2500   Teuchos::ArrayRCP<GO> cellDofs2GO(cellDofs2ArrayRCP.size(), GO());
2501   std::copy(cellDofs1ArrayRCP.getRawPtr(), cellDofs1ArrayRCP.getRawPtr()+cellDofs1ArrayRCP.size(),
2502             cellDofs1GO.getRawPtr());
2503   std::copy(cellDofs2ArrayRCP.getRawPtr(), cellDofs2ArrayRCP.getRawPtr()+cellDofs2ArrayRCP.size(),
2504             cellDofs2GO.getRawPtr());
2505   Teuchos::ArrayRCP<const GO> cellDofs1GOArrayRCP = cellDofs1GO.getConst();
2506   Teuchos::ArrayRCP<const GO> cellDofs2GOArrayRCP = cellDofs2GO.getConst();
2507 
2508   // Estimate the max number of entries per row
2509   // using a map (row indicies can be non-contiguous)
2510   GO maxEntriesPerRow1(0), maxEntriesPerRow2(0);
2511   {
2512     std::map<GO,GO> numEntriesCount1, numEntriesCount2;
2513     for (int i=0; i<numCells_; ++i) {
2514       for (int j=0; j<numLocalDofs1; ++j) {
2515         numEntriesCount1[GO(cellDofs1(myCellIds_[i],j))] += numLocalDofs1;
2516       }
2517       for (int j=0; j<numLocalDofs2; ++j) {
2518         numEntriesCount2[GO(cellDofs2(myCellIds_[i],j))] += numLocalDofs2;
2519       }
2520     }
2521     const auto rowIndexWithMaxEntries1
2522       = std::max_element(std::begin(numEntriesCount1), std::end(numEntriesCount1),
2523                          [](const std::pair<GO,GO> &pa, const std::pair<GO,GO> &pb) {
2524                            return pa.second < pb.second;
2525                          });
2526     const auto rowIndexWithMaxEntries2
2527       = std::max_element(std::begin(numEntriesCount2), std::end(numEntriesCount2),
2528                          [](const std::pair<GO,GO> &pa, const std::pair<GO,GO> &pb) {
2529                            return pa.second < pb.second;
2530                          });
2531     if (!numEntriesCount1.empty())
2532       maxEntriesPerRow1 = rowIndexWithMaxEntries1->second;
2533     if (!numEntriesCount2.empty())
2534       maxEntriesPerRow2 = rowIndexWithMaxEntries2->second;
2535   }
2536 
2537   matJ1Graph_ = ROL::makePtr<Tpetra::CrsGraph<>>(myUniqueStateMap_, maxEntriesPerRow1);
2538   for (int i=0; i<numCells_; ++i) {
2539     for (int j=0; j<numLocalDofs1; ++j) {
2540       matJ1Graph_->insertGlobalIndices(GO(cellDofs1(myCellIds_[i],j)),
2541         cellDofs1GOArrayRCP(myCellIds_[i]*numLocalDofs1, numLocalDofs1));
2542     }
2543   }
2544   matJ1Graph_->fillComplete(myUniqueStateMap_,myUniqueStateMap_);
2545   matR1Graph_  = matJ1Graph_;
2546   matH11Graph_ = matJ1Graph_;
2547 
2548   matJ2Graph_ = ROL::makePtr<Tpetra::CrsGraph<>>(myUniqueStateMap_, std::max(maxEntriesPerRow1,maxEntriesPerRow2));
2549   for (int i=0; i<numCells_; ++i) {
2550     for (int j=0; j<numLocalDofs1; ++j) {
2551       matJ2Graph_->insertGlobalIndices(GO(cellDofs1(myCellIds_[i],j)),
2552         cellDofs2GOArrayRCP(myCellIds_[i]*numLocalDofs2, numLocalDofs2));
2553     }
2554   }
2555   matJ2Graph_->fillComplete(myUniqueControlMap_,myUniqueStateMap_);
2556   matH21Graph_ = matJ2Graph_;
2557 
2558   matH12Graph_ = ROL::makePtr<Tpetra::CrsGraph<>>(myUniqueControlMap_, maxEntriesPerRow1);
2559   for (int i=0; i<numCells_; ++i) {
2560     for (int j=0; j<numLocalDofs2; ++j) {
2561       matH12Graph_->insertGlobalIndices(GO(cellDofs2(myCellIds_[i],j)),
2562         cellDofs1GOArrayRCP(myCellIds_[i]*numLocalDofs1, numLocalDofs1));
2563     }
2564   }
2565   matH12Graph_->fillComplete(myUniqueStateMap_,myUniqueControlMap_);
2566 
2567   matR2Graph_ = ROL::makePtr<Tpetra::CrsGraph<>>(myUniqueControlMap_, maxEntriesPerRow2);
2568   for (int i=0; i<numCells_; ++i) {
2569     for (int j=0; j<numLocalDofs2; ++j) {
2570       matR2Graph_->insertGlobalIndices(GO(cellDofs2(myCellIds_[i],j)),
2571         cellDofs2GOArrayRCP(myCellIds_[i]*numLocalDofs2, numLocalDofs2));
2572     }
2573   }
2574   matR2Graph_->fillComplete(myUniqueControlMap_,myUniqueControlMap_);
2575   matH22Graph_ = matR2Graph_;
2576 
2577   if (verbose_ && myRank_==0) {
2578     outStream << "Initialized parallel structures." << std::endl;
2579   }
2580 }
2581 
2582 template<class Real>
setCellNodes(std::ostream & outStream)2583 void Assembler<Real>::setCellNodes(std::ostream &outStream) {
2584   // Build volume cell nodes
2585   shards::CellTopology cellType = basisPtrs1_[0]->getBaseCellTopology();
2586   int spaceDim = cellType.getDimension();
2587   int numNodesPerCell = cellType.getNodeCount();
2588   volCellNodes_ = ROL::makePtr<Intrepid::FieldContainer<Real>>(numCells_, numNodesPerCell, spaceDim);
2589   Intrepid::FieldContainer<Real> &nodes = *meshMgr_->getNodes();
2590   Intrepid::FieldContainer<int>  &ctn   = *meshMgr_->getCellToNodeMap();
2591   for (int i=0; i<numCells_; ++i) {
2592     for (int j=0; j<numNodesPerCell; ++j) {
2593       for (int k=0; k<spaceDim; ++k) {
2594         (*volCellNodes_)(i, j, k) = nodes(ctn(myCellIds_[i],j), k);
2595       }
2596     }
2597   }
2598   // Build boundary cell nodes
2599   bdryCellIds_    = meshMgr_->getSideSets((verbose_ && myRank_==0), outStream);
2600   int numSideSets = bdryCellIds_->size();
2601   if (numSideSets > 0) {
2602     bdryCellNodes_.resize(numSideSets);
2603     bdryCellLocIds_.resize(numSideSets);
2604     for (int i=0; i<numSideSets; ++i) {
2605       int numLocSides = (*bdryCellIds_)[i].size();
2606       bdryCellNodes_[i].resize(numLocSides);
2607       bdryCellLocIds_[i].resize(numLocSides);
2608       for (int j=0; j<numLocSides; ++j) {
2609         if ((*bdryCellIds_)[i][j].size() > 0) {
2610           int numCellsSide = (*bdryCellIds_)[i][j].size();
2611           for (int k=0; k<numCellsSide; ++k) {
2612             int idx = mapGlobalToLocalCellId((*bdryCellIds_)[i][j][k]);
2613             if (idx > -1) {
2614               bdryCellLocIds_[i][j].push_back(idx);
2615               //if (myRank_==1) {std::cout << "\nrank " << myRank_ << "   bcid " << i << "  " << j << "  " << k << "  " << myCellIds_[idx] << "  " << idx;}
2616             }
2617           }
2618           int myNumCellsSide = bdryCellLocIds_[i][j].size();
2619           if (myNumCellsSide > 0) {
2620             bdryCellNodes_[i][j] = ROL::makePtr<Intrepid::FieldContainer<Real>>(myNumCellsSide, numNodesPerCell, spaceDim);
2621           }
2622           for (int k=0; k<myNumCellsSide; ++k) {
2623             for (int l=0; l<numNodesPerCell; ++l) {
2624               for (int m=0; m<spaceDim; ++m) {
2625                 (*bdryCellNodes_[i][j])(k, l, m) = nodes(ctn(myCellIds_[bdryCellLocIds_[i][j][k]],l), m);
2626               }
2627             }
2628           }
2629         }
2630         //if ((myRank_==1) && (myNumCellsSide > 0)) {std::cout << (*bdryCellNodes_[i][j]);}
2631       }
2632     }
2633   }
2634   bdryCellNodes_.resize(numSideSets);
2635 }
2636 
2637 template<class Real>
mapGlobalToLocalCellId(const int & gid)2638 int Assembler<Real>::mapGlobalToLocalCellId(const int & gid) {
2639   auto it = std::find(myCellIds_.begin(),myCellIds_.end(),gid);
2640   if (it != myCellIds_.end()) {
2641     return it-myCellIds_.begin();
2642   }
2643   else {
2644     return -1;
2645   }
2646 /*
2647   int minId = cellOffsets_[myRank_];
2648   int maxId = cellOffsets_[myRank_]+numCells_-1;
2649   if ((gid >= minId) && (gid <= maxId)) {
2650     return (gid - cellOffsets_[myRank_]);
2651   }
2652   else {
2653     return -1;
2654   }
2655 */
2656 }
2657 
2658 template<class Real>
getCoeffFromStateVector(ROL::Ptr<Intrepid::FieldContainer<Real>> & xcoeff,const ROL::Ptr<const Tpetra::MultiVector<>> & x) const2659 void Assembler<Real>::getCoeffFromStateVector(ROL::Ptr<Intrepid::FieldContainer<Real>> &xcoeff,
2660                                         const ROL::Ptr<const Tpetra::MultiVector<>> &x) const {
2661   if ( x != ROL::nullPtr ) {
2662     // Perform import onto myOverlapMap
2663     ROL::Ptr<Tpetra::MultiVector<>> xshared =
2664       ROL::makePtr<Tpetra::MultiVector<>>(myOverlapStateMap_, 1, true);
2665     Tpetra::Import<> importer(myUniqueStateMap_, myOverlapStateMap_);
2666     xshared->doImport(*x,importer,Tpetra::REPLACE);
2667     // Populate xcoeff
2668     Intrepid::FieldContainer<int> &cellDofs = *(dofMgr1_->getCellDofs());
2669     int lfs = dofMgr1_->getLocalFieldSize();
2670     xcoeff = ROL::makePtr<Intrepid::FieldContainer<Real>>(numCells_, lfs);
2671     Teuchos::ArrayRCP<const Real> xdata = xshared->get1dView();
2672     for (int i=0; i<numCells_; ++i) {
2673       for (int j=0; j<lfs; ++j) {
2674         (*xcoeff)(i,j) = xdata[xshared->getMap()->getLocalElement(cellDofs(myCellIds_[i],j))];
2675       }
2676     }
2677     dofMgr1_->transformToIntrepidPattern(xcoeff);
2678   }
2679   else {
2680     xcoeff = ROL::nullPtr;
2681   }
2682 }
2683 
2684 template<class Real>
getCoeffFromControlVector(ROL::Ptr<Intrepid::FieldContainer<Real>> & xcoeff,const ROL::Ptr<const Tpetra::MultiVector<>> & x) const2685 void Assembler<Real>::getCoeffFromControlVector(ROL::Ptr<Intrepid::FieldContainer<Real>> &xcoeff,
2686                                           const ROL::Ptr<const Tpetra::MultiVector<>> &x) const {
2687   if ( x != ROL::nullPtr ) {
2688     // Perform import onto myOverlapMap
2689     ROL::Ptr<Tpetra::MultiVector<>> xshared =
2690       ROL::makePtr<Tpetra::MultiVector<>>(myOverlapControlMap_, 1, true);
2691     Tpetra::Import<> importer(myUniqueControlMap_, myOverlapControlMap_);
2692     xshared->doImport(*x,importer,Tpetra::REPLACE);
2693     // Populate xcoeff
2694     Intrepid::FieldContainer<int> &cellDofs = *(dofMgr2_->getCellDofs());
2695     int lfs = dofMgr2_->getLocalFieldSize();
2696     xcoeff = ROL::makePtr<Intrepid::FieldContainer<Real>>(numCells_, lfs);
2697     Teuchos::ArrayRCP<const Real> xdata = xshared->get1dView();
2698     for (int i=0; i<numCells_; ++i) {
2699       for (int j=0; j<lfs; ++j) {
2700         (*xcoeff)(i,j) = xdata[xshared->getMap()->getLocalElement(cellDofs(myCellIds_[i],j))];
2701       }
2702     }
2703     dofMgr2_->transformToIntrepidPattern(xcoeff);
2704   }
2705   else {
2706     xcoeff = ROL::nullPtr;
2707   }
2708 }
2709 
2710 /***************************************************************************/
2711 /****** GENERIC ASSEMBLY ROUTINES ******************************************/
2712 /***************************************************************************/
2713 template<class Real>
assembleScalar(ROL::Ptr<Intrepid::FieldContainer<Real>> & val)2714 Real Assembler<Real>::assembleScalar(ROL::Ptr<Intrepid::FieldContainer<Real>> &val) {
2715   // Assembly
2716   if ( val != ROL::nullPtr ) {
2717     Real myval(0), gval(0);
2718     for (int i=0; i<numCells_; ++i) {
2719       myval += (*val)(i);
2720     }
2721     Teuchos::reduceAll<int,Real>(*comm_,Teuchos::REDUCE_SUM,1,&myval,&gval);
2722     return gval;
2723   }
2724   return static_cast<Real>(0);
2725 }
2726 
2727 template<class Real>
assembleFieldVector(ROL::Ptr<Tpetra::MultiVector<>> & v,ROL::Ptr<Intrepid::FieldContainer<Real>> & val,ROL::Ptr<Tpetra::MultiVector<>> & vecOverlap,const ROL::Ptr<DofManager<Real>> & dofMgr)2728 void Assembler<Real>::assembleFieldVector(ROL::Ptr<Tpetra::MultiVector<>> &v,
2729                                           ROL::Ptr<Intrepid::FieldContainer<Real>> &val,
2730                                           ROL::Ptr<Tpetra::MultiVector<>> &vecOverlap,
2731                                           const ROL::Ptr<DofManager<Real>> &dofMgr) {
2732   // Set residual vectors to zero
2733   v->putScalar(static_cast<Real>(0));
2734   vecOverlap->putScalar(static_cast<Real>(0));
2735   // Get degrees of freedom
2736   Intrepid::FieldContainer<int> &cellDofs = *(dofMgr->getCellDofs());
2737   int numLocalDofs = cellDofs.dimension(1);
2738   // Transform values
2739   transformToFieldPattern(val,dofMgr);
2740   // assembly on the overlap map
2741   for (int i=0; i<numCells_; ++i) {
2742     for (int j=0; j<numLocalDofs; ++j) {
2743       vecOverlap->sumIntoGlobalValue(cellDofs(myCellIds_[i],j),0,(*val)(i,j));
2744     }
2745   }
2746   // change map
2747   Tpetra::Export<> exporter(vecOverlap->getMap(), v->getMap()); // redistribution
2748   v->doExport(*vecOverlap, exporter, Tpetra::ADD);              // from the overlap map to the unique map
2749 }
2750 
2751 template<class Real>
assembleParamVector(ROL::Ptr<std::vector<Real>> & v,std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & val)2752 void Assembler<Real>::assembleParamVector(ROL::Ptr<std::vector<Real>> &v,
2753                                           std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> &val) {
2754   int size = v->size();
2755   v->assign(size,0);
2756 //  for (int i = 0; i < size; ++i) {
2757 //    dofMgr_->transformToFieldPattern(val[i]);
2758 //  }
2759   // Assembly
2760   std::vector<Real> myVal(size,0);
2761   for (int j = 0; j < size; ++j) {
2762     if ( val[j] != ROL::nullPtr ) {
2763       for (int i=0; i<numCells_; ++i) {
2764         myVal[j] += (*val[j])(i);
2765       }
2766     }
2767   }
2768   Teuchos::reduceAll<int,Real>(*comm_,Teuchos::REDUCE_SUM,size,&myVal[0],&(*v)[0]);
2769 }
2770 
2771 template<class Real>
assembleFieldMatrix(ROL::Ptr<Tpetra::CrsMatrix<>> & M,ROL::Ptr<Intrepid::FieldContainer<Real>> & val,const ROL::Ptr<DofManager<Real>> & dofMgr1,const ROL::Ptr<DofManager<Real>> & dofMgr2)2772 void Assembler<Real>::assembleFieldMatrix(ROL::Ptr<Tpetra::CrsMatrix<>> &M,
2773                                           ROL::Ptr<Intrepid::FieldContainer<Real>> &val,
2774                                           const ROL::Ptr<DofManager<Real>> &dofMgr1,
2775                                           const ROL::Ptr<DofManager<Real>> &dofMgr2) {
2776   // Transform data
2777   transformToFieldPattern(val,dofMgr1,dofMgr2);
2778   // Zero PDE Jacobian
2779   M->resumeFill(); M->setAllToScalar(static_cast<Real>(0));
2780   // Assemble PDE Jacobian
2781   Intrepid::FieldContainer<int> &cellDofs1 = *(dofMgr1->getCellDofs());
2782   Intrepid::FieldContainer<int> &cellDofs2 = *(dofMgr2->getCellDofs());
2783   int numLocalDofs1 = cellDofs1.dimension(1);
2784   int numLocalDofs2 = cellDofs2.dimension(1);
2785   int numLocalMatEntries = numLocalDofs1 * numLocalDofs2;
2786   Teuchos::ArrayRCP<const int> cellDofs2ArrayRCP = cellDofs2.getData();
2787   Teuchos::ArrayRCP<GO> cellDofs2GO(cellDofs2ArrayRCP.size(), GO());
2788   std::copy(cellDofs2ArrayRCP.getRawPtr(), cellDofs2ArrayRCP.getRawPtr()+cellDofs2ArrayRCP.size(),
2789             cellDofs2GO.getRawPtr());
2790   Teuchos::ArrayRCP<const GO> cellDofs2GOArrayRCP = cellDofs2GO.getConst();
2791   Teuchos::ArrayRCP<const Real> valArrayRCP = val->getData();
2792   for (int i=0; i<numCells_; ++i) {
2793     for (int j=0; j<numLocalDofs1; ++j) {
2794       M->sumIntoGlobalValues(GO(cellDofs1(myCellIds_[i],j)),
2795                              cellDofs2GOArrayRCP(myCellIds_[i] * numLocalDofs2, numLocalDofs2),
2796                              valArrayRCP(i*numLocalMatEntries+j*numLocalDofs2, numLocalDofs2));
2797     }
2798   }
2799   M->fillComplete();
2800 }
2801 
2802 template<class Real>
assembleParamFieldMatrix(ROL::Ptr<Tpetra::MultiVector<>> & M,std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & val,ROL::Ptr<Tpetra::MultiVector<>> & matOverlap,const ROL::Ptr<DofManager<Real>> & dofMgr)2803 void Assembler<Real>::assembleParamFieldMatrix(ROL::Ptr<Tpetra::MultiVector<>> &M,
2804                                                std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> &val,
2805                                                ROL::Ptr<Tpetra::MultiVector<>> &matOverlap,
2806                                                const ROL::Ptr<DofManager<Real>> &dofMgr) {
2807   // Initialize res
2808   int size = M->getNumVectors();
2809   // Compute PDE local Jacobian wrt parametric controls
2810   for (int i = 0; i < size; ++i) {
2811     transformToFieldPattern(val[i],dofMgr);
2812   }
2813   // Assemble PDE Jacobian wrt parametric controls
2814   M->scale(static_cast<Real>(0));
2815   matOverlap->scale(static_cast<Real>(0));
2816   for (int k = 0; k < size; ++k) {
2817     Intrepid::FieldContainer<int> &cellDofs = *(dofMgr->getCellDofs());
2818     int numLocalDofs = cellDofs.dimension(1);
2819     // assembly on the overlap map
2820     for (int i=0; i<numCells_; ++i) {
2821       for (int j=0; j<numLocalDofs; ++j) {
2822         matOverlap->sumIntoGlobalValue(cellDofs(myCellIds_[i],j),
2823                                         k,(*val[k])[i*numLocalDofs+j]);
2824       }
2825     }
2826     // change map
2827     Tpetra::Export<> exporter(matOverlap->getMap(), M->getMap()); // redistribution
2828     M->doExport(*matOverlap, exporter, Tpetra::ADD);              // from the overlap map to the unique map
2829   }
2830 }
2831 
2832 template<class Real>
assembleParamMatrix(ROL::Ptr<std::vector<std::vector<Real>>> & M,std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> & val,const ROL::Ptr<DofManager<Real>> & dofMgr)2833 void Assembler<Real>::assembleParamMatrix(ROL::Ptr<std::vector<std::vector<Real>>> &M,
2834                                           std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> &val,
2835                                           const ROL::Ptr<DofManager<Real>> &dofMgr) {
2836   // Initialize local matrix
2837   int size = M->size();
2838   std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> tmp(size,ROL::nullPtr);
2839   // Compute local matrix
2840   for (int i = 0; i < size; ++i) {
2841     for (int j = 0; j < size; ++j) {
2842       transformToFieldPattern(val[i][j],dofMgr);
2843     }
2844   }
2845   // Assemble PDE Jacobian wrt parametric controls
2846   int cnt = 0, matSize = static_cast<int>(0.5*static_cast<Real>((size+1)*size));
2847   std::vector<Real> myMat(matSize,static_cast<Real>(0));
2848   std::vector<Real> globMat(matSize,static_cast<Real>(0));
2849   for (int k = 0; k < size; ++k) {
2850     for (int j = k; j < size; ++j) {
2851       for (int i=0; i<numCells_; ++i) {
2852         myMat[cnt] += (*(val[k][j]))(i);
2853       }
2854       cnt++;
2855     }
2856   }
2857   Teuchos::reduceAll<int,Real>(*comm_,Teuchos::REDUCE_SUM,matSize,&myMat[0],&globMat[0]);
2858   cnt = 0;
2859   for (int k = 0; k < size; ++k) {
2860     for (int j = k; j < size; ++j) {
2861       (*M)[k][j] += globMat[cnt];
2862       if ( j != k ) {
2863         (*M)[j][k] += globMat[cnt];
2864       }
2865       cnt++;
2866     }
2867   }
2868 }
2869 
2870 template<class Real>
transformToFieldPattern(const ROL::Ptr<Intrepid::FieldContainer<Real>> & array,const ROL::Ptr<DofManager<Real>> & dofMgr1,const ROL::Ptr<DofManager<Real>> & dofMgr2) const2871 void Assembler<Real>::transformToFieldPattern(const ROL::Ptr<Intrepid::FieldContainer<Real>> &array,
2872                                               const ROL::Ptr<DofManager<Real>> &dofMgr1,
2873                                               const ROL::Ptr<DofManager<Real>> &dofMgr2) const {
2874   if ( array != ROL::nullPtr ) {
2875     int rank = array->rank();
2876     int nc   = array->dimension(0);
2877     if ( rank == 2 ) {
2878       int nf = array->dimension(1);
2879       Intrepid::FieldContainer<Real> tmp(nc, nf);
2880       for (int c = 0; c < nc; ++c) {
2881         for (int f = 0; f < nf; ++f) {
2882           tmp(c, dofMgr1->mapToFieldPattern(f)) = (*array)(c, f);
2883         }
2884       }
2885       *array = tmp;
2886     }
2887     else if (rank == 3 ) {
2888       int nf1 = array->dimension(1);
2889       int nf2 = array->dimension(2);
2890       Intrepid::FieldContainer<Real> tmp(nc, nf1, nf2);
2891       for (int c = 0; c < nc; ++c) {
2892         for (int f1 = 0; f1 < nf1; ++f1) {
2893           for (int f2 = 0; f2 < nf2; ++f2) {
2894             tmp(c, dofMgr1->mapToFieldPattern(f1), dofMgr2->mapToFieldPattern(f2)) = (*array)(c, f1, f2);
2895           }
2896         }
2897       }
2898       *array = tmp;
2899     }
2900     else {
2901       TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
2902         ">>> PDE-OPT/TOOLS/assembler.hpp (transformToFieldPattern): Input array rank not 2 or 3!");
2903     }
2904   }
2905 }
2906 
2907 #endif
2908