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  pde.hpp
45     \brief Implements the local PDE interface for the Poisson control problem.
46 */
47 
48 #ifndef PDE_ADV_DIFF_SUR_HPP
49 #define PDE_ADV_DIFF_SUR_HPP
50 
51 #include "../../TOOLS/pde.hpp"
52 #include "../../TOOLS/fe.hpp"
53 
54 #include "Intrepid_HGRAD_QUAD_C1_FEM.hpp"
55 #include "Intrepid_HGRAD_QUAD_C2_FEM.hpp"
56 #include "Intrepid_HGRAD_HEX_C1_FEM.hpp"
57 #include "Intrepid_HGRAD_HEX_C2_FEM.hpp"
58 #include "Intrepid_DefaultCubatureFactory.hpp"
59 #include "Intrepid_FunctionSpaceTools.hpp"
60 #include "Intrepid_CellTools.hpp"
61 
62 #include "ROL_Ptr.hpp"
63 
64 template <class Real>
65 class PDE_adv_diff : public PDE<Real> {
66 private:
67   // Finite element basis information
68   ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>> basisPtr_;
69   std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> basisPtrs_;
70   ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>> basisPtr2_;
71   std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> basisPtrs2_;
72   // Cell cubature information
73   ROL::Ptr<Intrepid::Cubature<Real>> cellCub_;
74   // Cell node information
75   ROL::Ptr<Intrepid::FieldContainer<Real>> volCellNodes_;
76   std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> bdryCellNodes_;
77   std::vector<std::vector<std::vector<int>>> bdryCellLocIds_;
78   // Finite element definition
79   ROL::Ptr<FE<Real>> fe_vol_, fe_ctrl_;
80   // Local degrees of freedom on boundary, for each side of the reference cell (first index).
81   std::vector<std::vector<int>> fidx_;
82   // Coordinates of degrees freedom on boundary cells.
83   // Indexing:  [sideset number][local side id](cell number, value at dof)
84   std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> bdryCellDofValues_;
85 
86   int nx_, ny_;
87   Real XL_, XU_, YL_, YU_;
88   bool usePC_;
89 
90 public:
PDE_adv_diff(Teuchos::ParameterList & parlist)91   PDE_adv_diff(Teuchos::ParameterList &parlist) {
92     // Finite element fields.
93     int basisOrder = parlist.sublist("Problem").get("Order of FE Discretization",1);
94     int cubDegree  = parlist.sublist("Problem").get("Cubature Degree",4);
95     int probDim    = parlist.sublist("Problem").get("Problem Dimension",2);
96     if (probDim == 2) {
97       if (basisOrder == 1) {
98         basisPtr_ = ROL::makePtr<Intrepid::Basis_HGRAD_QUAD_C1_FEM<Real, Intrepid::FieldContainer<Real>>>();
99       }
100       else if (basisOrder == 2) {
101         basisPtr_ = ROL::makePtr<Intrepid::Basis_HGRAD_QUAD_C2_FEM<Real, Intrepid::FieldContainer<Real>>>();
102       }
103     }
104     else if (probDim == 3) {
105       if (basisOrder == 1) {
106         basisPtr_ = ROL::makePtr<Intrepid::Basis_HGRAD_HEX_C1_FEM<Real, Intrepid::FieldContainer<Real>>>();
107       }
108       else if (basisOrder == 2) {
109         basisPtr_ = ROL::makePtr<Intrepid::Basis_HGRAD_HEX_C2_FEM<Real, Intrepid::FieldContainer<Real>>>();
110       }
111     }
112     basisPtrs_.clear(); basisPtrs_.push_back(basisPtr_);
113     // Quadrature rules.
114     shards::CellTopology cellType = basisPtr_->getBaseCellTopology();        // get the cell type from any basis
115     Intrepid::DefaultCubatureFactory<Real> cubFactory;                       // create cubature factory
116     cellCub_ = cubFactory.create(cellType, cubDegree);                       // create default cubature
117 
118     nx_ = parlist.sublist("Problem").get("Number of X-Cells", 4);
119     ny_ = parlist.sublist("Problem").get("Number of Y-Cells", 2);
120     XL_ = parlist.sublist("Geometry").get("X0", 0.0);
121     YL_ = parlist.sublist("Geometry").get("Y0", 0.0);
122     XU_ = XL_ + parlist.sublist("Geometry").get("Width",  2.0);
123     YU_ = YL_ + parlist.sublist("Geometry").get("Height", 1.0);
124     usePC_ = parlist.sublist("Problem").get("Piecewise Constant Controls", true);
125     if (!usePC_) {
126       if (probDim == 2) {
127         basisPtr2_ = ROL::makePtr<Intrepid::Basis_HGRAD_QUAD_C1_FEM<Real, Intrepid::FieldContainer<Real>>>();
128       }
129       else if (probDim == 3) {
130         basisPtr2_ = ROL::makePtr<Intrepid::Basis_HGRAD_HEX_C1_FEM<Real, Intrepid::FieldContainer<Real>>>();
131       }
132       basisPtrs2_.clear(); basisPtrs2_.push_back(basisPtr2_);
133     }
134   }
135 
residual(ROL::Ptr<Intrepid::FieldContainer<Real>> & res,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)136   void residual(ROL::Ptr<Intrepid::FieldContainer<Real>> & res,
137                 const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
138                 const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
139                 const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
140     // GET DIMENSIONS
141     int c = fe_vol_->gradN()->dimension(0);
142     int f = fe_vol_->gradN()->dimension(1);
143     int p = fe_vol_->gradN()->dimension(2);
144     int d = fe_vol_->gradN()->dimension(3);
145     // INITIALIZE RESIDUAL AND STORAGE
146     res = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f);
147     ROL::Ptr<Intrepid::FieldContainer<Real>> kappa, V;
148     ROL::Ptr<Intrepid::FieldContainer<Real>> gradU_eval, kappa_gradU, V_gradU, valZ_eval;
149     kappa       = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
150     V           = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p, d);
151     gradU_eval  = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p, d);
152     kappa_gradU = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p, d);
153     V_gradU     = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
154     valZ_eval   = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
155     // COMPUTE PDE COEFFICIENTS
156     computeCoefficients(kappa,V);
157     // EVALUE GRADIENT OF U AT QUADRATURE POINTS
158     fe_vol_->evaluateGradient(gradU_eval, u_coeff);
159     // COMPUTE DIFFUSION TERM
160     Intrepid::FunctionSpaceTools::tensorMultiplyDataData<Real>(*kappa_gradU,
161                                                                *kappa,
162                                                                *gradU_eval);
163     Intrepid::FunctionSpaceTools::integrate<Real>(*res,
164                                                   *kappa_gradU,
165                                                   *fe_vol_->gradNdetJ(),
166                                                   Intrepid::COMP_CPP, false);
167     // ADD ADVECTION TERM TO RESIDUAL
168     Intrepid::FunctionSpaceTools::dotMultiplyDataData<Real>(*V_gradU,
169                                                             *V,
170                                                             *gradU_eval);
171     Intrepid::FunctionSpaceTools::integrate<Real>(*res,
172                                                   *V_gradU,
173                                                   *fe_vol_->NdetJ(),
174                                                   Intrepid::COMP_CPP, true);
175 
176     // ADD CONTROL TERM TO RESIDUAL
177     if (z_coeff != ROL::nullPtr) {
178       fe_ctrl_->evaluateValue(valZ_eval, z_coeff);
179       Intrepid::RealSpaceTools<Real>::scale(*valZ_eval,static_cast<Real>(-1));
180       Intrepid::FunctionSpaceTools::integrate<Real>(*res,
181                                                     *valZ_eval,
182                                                     *fe_vol_->NdetJ(),
183                                                     Intrepid::COMP_CPP, true);
184     }
185     else {
186       addControlOperator(valZ_eval,z_param);
187       Intrepid::FunctionSpaceTools::integrate<Real>(*res,
188                                                     *valZ_eval,
189                                                     *fe_vol_->NdetJ(),
190                                                     Intrepid::COMP_CPP, true);
191     }
192     // APPLY DIRICHLET CONDITIONS
193     int numLocalSideIds = bdryCellLocIds_[0].size();
194     for (int j = 0; j < numLocalSideIds; ++j) {
195       int numCellsSide = bdryCellLocIds_[0][j].size();
196       int numBdryDofs = fidx_[j].size();
197       for (int k = 0; k < numCellsSide; ++k) {
198         int cidx = bdryCellLocIds_[0][j][k];
199         for (int l = 0; l < numBdryDofs; ++l) {
200           (*res)(cidx,fidx_[j][l])
201             = (*u_coeff)(cidx,fidx_[j][l]) - (*bdryCellDofValues_[0][j])(k,fidx_[j][l]);
202         }
203       }
204     }
205   }
206 
Jacobian_1(ROL::Ptr<Intrepid::FieldContainer<Real>> & jac,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)207   void Jacobian_1(ROL::Ptr<Intrepid::FieldContainer<Real>> & jac,
208                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
209                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
210                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
211     // GET DIMENSIONS
212     int c = fe_vol_->gradN()->dimension(0);
213     int f = fe_vol_->gradN()->dimension(1);
214     int p = fe_vol_->gradN()->dimension(2);
215     int d = fe_vol_->gradN()->dimension(3);
216     // INITILAIZE JACOBIAN AND STORAGE
217     jac = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f, f);
218     ROL::Ptr<Intrepid::FieldContainer<Real>> kappa, V, kappa_gradN, V_gradN;
219     kappa       = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
220     V           = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p, d);
221     kappa_gradN = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f, p, d);
222     V_gradN     = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f, p);
223     // COMPUTE PDE COEFFICIENTS
224     computeCoefficients(kappa,V);
225     // COMPUTE DIFFUSION TERM
226     Intrepid::FunctionSpaceTools::tensorMultiplyDataField<Real>(*kappa_gradN,
227                                                                 *kappa,
228                                                                 *fe_vol_->gradN());
229     Intrepid::FunctionSpaceTools::integrate<Real>(*jac,
230                                                   *kappa_gradN,
231                                                   *fe_vol_->gradNdetJ(),
232                                                   Intrepid::COMP_CPP, false);
233     // ADD ADVECTION TERM TO JACOBIAN
234     Intrepid::FunctionSpaceTools::dotMultiplyDataField<Real>(*V_gradN,
235                                                              *V,
236                                                              *fe_vol_->gradN());
237     Intrepid::FunctionSpaceTools::integrate<Real>(*jac,
238                                                   *fe_vol_->NdetJ(),
239                                                   *V_gradN,
240                                                   Intrepid::COMP_CPP, true);
241     // APPLY DIRICHLET CONDITIONS
242     int numLocalSideIds = bdryCellLocIds_[0].size();
243     for (int j = 0; j < numLocalSideIds; ++j) {
244       int numCellsSide = bdryCellLocIds_[0][j].size();
245       int numBdryDofs = fidx_[j].size();
246       for (int k = 0; k < numCellsSide; ++k) {
247         int cidx = bdryCellLocIds_[0][j][k];
248         for (int l = 0; l < numBdryDofs; ++l) {
249           //std::cout << "\n   j=" << j << "  l=" << l << "  " << fidx[j][l];
250           for (int m = 0; m < f; ++m) {
251             (*jac)(cidx,fidx_[j][l],m) = static_cast<Real>(0);
252           }
253           (*jac)(cidx,fidx_[j][l],fidx_[j][l]) = static_cast<Real>(1);
254         }
255       }
256     }
257   }
258 
Jacobian_2(ROL::Ptr<Intrepid::FieldContainer<Real>> & jac,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)259   void Jacobian_2(ROL::Ptr<Intrepid::FieldContainer<Real>> & jac,
260                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
261                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
262                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
263     if (z_coeff != ROL::nullPtr) {
264       // GET DIMENSIONS
265       int c = fe_vol_->N()->dimension(0);
266       int f1 = fe_vol_->N()->dimension(1);
267       int f2 = fe_ctrl_->N()->dimension(1);
268       // INITIALIZE RIESZ
269       jac  = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f1, f2);
270       Intrepid::FunctionSpaceTools::integrate<Real>(*jac,
271                                                     *fe_vol_->N(),
272                                                     *fe_ctrl_->NdetJ(),
273                                                     Intrepid::COMP_CPP, false);
274       //*jac = *fe_vol_->massMat();
275       Intrepid::RealSpaceTools<Real>::scale(*jac,static_cast<Real>(-1));
276       // APPLY DIRICHLET CONDITIONS
277       int numLocalSideIds = bdryCellLocIds_[0].size();
278       for (int j = 0; j < numLocalSideIds; ++j) {
279         int numCellsSide = bdryCellLocIds_[0][j].size();
280         int numBdryDofs = fidx_[j].size();
281         for (int k = 0; k < numCellsSide; ++k) {
282           int cidx = bdryCellLocIds_[0][j][k];
283           for (int l = 0; l < numBdryDofs; ++l) {
284             //std::cout << "\n   j=" << j << "  l=" << l << "  " << fidx[j][l];
285             for (int m = 0; m < f2; ++m) {
286               (*jac)(cidx,fidx_[j][l],m) = static_cast<Real>(0);
287             }
288           }
289         }
290       }
291     }
292     else {
293       throw Exception::Zero(">>> (PDE_stoch_adv_diff::Jacobian_2): Jacobian is zero.");
294     }
295   }
296 
Jacobian_3(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & jac,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)297   void Jacobian_3(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & jac,
298                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
299                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
300                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
301     if (z_coeff != ROL::nullPtr) {
302       throw Exception::Zero(">>> (PDE_stoch_adv_diff::Jacobian_3): Jacobian is zero.");
303     }
304     else {
305       // GET DIMENSIONS
306       int c = fe_vol_->gradN()->dimension(0);
307       int f = fe_vol_->gradN()->dimension(1);
308       int p = fe_vol_->gradN()->dimension(2);
309       // ADD CONTROL TERM TO RESIDUAL
310       ROL::Ptr<Intrepid::FieldContainer<Real>> ctrl
311         = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
312       ROL::Ptr<Intrepid::FieldContainer<Real>> B
313         = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, p);
314       for (int i = 0; i < nx_; ++i) {
315         for (int j = 0; j < ny_; ++j) {
316           int ind = i + j*nx_;
317           jac[ind] = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f);
318           addControlJaobian(B,i,j);
319           Intrepid::FunctionSpaceTools::integrate<Real>(*jac[ind],
320                                                         *B,
321                                                         *fe_vol_->NdetJ(),
322                                                         Intrepid::COMP_CPP, false);
323           // APPLY DIRICHLET CONDITIONS
324           int numLocalSideIds = bdryCellLocIds_[0].size();
325           for (int k = 0; k < numLocalSideIds; ++k) {
326             int numCellsSide = bdryCellLocIds_[0][k].size();
327             int numBdryDofs = fidx_[k].size();
328             for (int l = 0; l < numCellsSide; ++l) {
329               int cidx = bdryCellLocIds_[0][k][l];
330               for (int m = 0; m < numBdryDofs; ++m) {
331                 (*(jac[ind]))(cidx,fidx_[k][m]) = static_cast<Real>(0);
332               }
333             }
334           }
335         }
336       }
337     }
338   }
339 
Hessian_11(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)340   void Hessian_11(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,
341                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
342                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
343                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
344                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
345     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_11): Hessian is zero.");
346   }
347 
Hessian_12(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)348   void Hessian_12(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,
349                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
350                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
351                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
352                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
353     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_12): Hessian is zero.");
354   }
355 
Hessian_13(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)356   void Hessian_13(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,
357                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
358                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
359                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
360                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
361     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_13): Hessian is zero.");
362   }
363 
Hessian_21(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)364   void Hessian_21(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,
365                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
366                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
367                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
368                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
369     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_21): Hessian is zero.");
370   }
371 
Hessian_22(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)372   void Hessian_22(ROL::Ptr<Intrepid::FieldContainer<Real>> & hess,
373                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
374                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
375                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
376                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
377     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_22): Hessian is zero.");
378   }
379 
Hessian_23(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)380   void Hessian_23(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,
381                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
382                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
383                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
384                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
385     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_23): Hessian is zero.");
386   }
387 
Hessian_31(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)388   void Hessian_31(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,
389                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
390                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
391                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
392                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
393     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_31): Hessian is zero.");
394   }
395 
Hessian_32(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)396   void Hessian_32(std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>> & hess,
397                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
398                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
399                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
400                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
401     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_32): Hessian is zero.");
402   }
403 
Hessian_33(std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> & hess,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff=ROL::nullPtr,const ROL::Ptr<const std::vector<Real>> & z_param=ROL::nullPtr)404   void Hessian_33(std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> & hess,
405                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & l_coeff,
406                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & u_coeff,
407                   const ROL::Ptr<const Intrepid::FieldContainer<Real>> & z_coeff = ROL::nullPtr,
408                   const ROL::Ptr<const std::vector<Real>> & z_param = ROL::nullPtr) {
409     throw Exception::Zero(">>> (PDE_stoch_adv_diff::Hessian_33): Hessian is zero.");
410   }
411 
RieszMap_1(ROL::Ptr<Intrepid::FieldContainer<Real>> & riesz)412   void RieszMap_1(ROL::Ptr<Intrepid::FieldContainer<Real>> & riesz) {
413     // GET DIMENSIONS
414     int c = fe_vol_->N()->dimension(0);
415     int f = fe_vol_->N()->dimension(1);
416     // INITIALIZE RIESZ
417     riesz = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f, f);
418     *riesz = *fe_vol_->stiffMat();
419     Intrepid::RealSpaceTools<Real>::add(*riesz,*(fe_vol_->massMat()));
420   }
421 
RieszMap_2(ROL::Ptr<Intrepid::FieldContainer<Real>> & riesz)422   void RieszMap_2(ROL::Ptr<Intrepid::FieldContainer<Real>> & riesz) {
423     // GET DIMENSIONS
424     int c = fe_ctrl_->N()->dimension(0);
425     int f = fe_ctrl_->N()->dimension(1);
426     // INITIALIZE RIESZ
427     riesz = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f, f);
428     *riesz = *fe_ctrl_->massMat();
429   }
430 
getFields()431   std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> getFields() {
432     return basisPtrs_;
433   }
434 
getFields2()435   std::vector<ROL::Ptr<Intrepid::Basis<Real, Intrepid::FieldContainer<Real>>>> getFields2() {
436     return basisPtrs2_;
437   }
438 
setCellNodes(const ROL::Ptr<Intrepid::FieldContainer<Real>> & volCellNodes,const std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> & bdryCellNodes,const std::vector<std::vector<std::vector<int>>> & bdryCellLocIds)439   void setCellNodes(const ROL::Ptr<Intrepid::FieldContainer<Real>> &volCellNodes,
440                     const std::vector<std::vector<ROL::Ptr<Intrepid::FieldContainer<Real>>>> &bdryCellNodes,
441                     const std::vector<std::vector<std::vector<int>>> &bdryCellLocIds) {
442     volCellNodes_ = volCellNodes;
443     bdryCellNodes_ = bdryCellNodes;
444     bdryCellLocIds_ = bdryCellLocIds;
445     // Finite element definition.
446     fe_vol_ = ROL::makePtr<FE<Real>>(volCellNodes_,basisPtr_,cellCub_);
447     if (!usePC_) {
448       fe_ctrl_ = ROL::makePtr<FE<Real>>(volCellNodes_,basisPtr2_,cellCub_);
449     }
450     // Set local boundary DOFs.
451     fidx_ = fe_vol_->getBoundaryDofs();
452     // Compute Dirichlet values at DOFs.
453     int d = basisPtr_->getBaseCellTopology().getDimension();
454     int numSidesets = bdryCellLocIds_.size();
455     bdryCellDofValues_.resize(numSidesets);
456     for (int i=0; i<numSidesets; ++i) {
457       int numLocSides = bdryCellLocIds_[i].size();
458       bdryCellDofValues_[i].resize(numLocSides);
459       for (int j=0; j<numLocSides; ++j) {
460         int c = bdryCellLocIds_[i][j].size();
461         int f = basisPtr_->getCardinality();
462         bdryCellDofValues_[i][j] = ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f);
463         ROL::Ptr<Intrepid::FieldContainer<Real>> coords =
464           ROL::makePtr<Intrepid::FieldContainer<Real>>(c, f, d);
465         if (c > 0) {
466           fe_vol_->computeDofCoords(coords, bdryCellNodes_[i][j]);
467         }
468         for (int k=0; k<c; ++k) {
469           for (int l=0; l<f; ++l) {
470             std::vector<Real> dofpoint(d);
471             for (int m=0; m<d; ++m) {
472               dofpoint[m] = (*coords)(k, l, m);
473             }
474             (*bdryCellDofValues_[i][j])(k, l) = evaluateDirichlet(dofpoint, i, j);
475           }
476         }
477       }
478     }
479   }
480 
getFE(void) const481   const ROL::Ptr<FE<Real>> getFE(void) const {
482     return fe_vol_;
483   }
484 
getFE2(void) const485   const ROL::Ptr<FE<Real>> getFE2(void) const {
486     return fe_ctrl_;
487   }
488 
print(void) const489   void print(void) const {
490     std::ofstream xfile, yfile;
491     xfile.open("X.txt");
492     yfile.open("Y.txt");
493     for (int i = 0; i < nx_; ++i) {
494       for (int j = 0; j < ny_; ++j) {
495         xfile << i << std::endl;
496         yfile << j << std::endl;
497       }
498     }
499     xfile.close();
500     yfile.close();
501   }
502 
503 private:
504 
evaluateDirichlet(const std::vector<Real> & coords,int sideset,int locSideId) const505   Real evaluateDirichlet(const std::vector<Real> & coords, int sideset, int locSideId) const {
506     return static_cast<Real>(0);
507   }
508 
evaluateDiffusivity(const std::vector<Real> & x) const509   Real evaluateDiffusivity(const std::vector<Real> &x) const {
510     return static_cast<Real>(0.01);
511   }
512 
evaluateVelocity(std::vector<Real> & adv,const std::vector<Real> & x) const513   void evaluateVelocity(std::vector<Real> &adv, const std::vector<Real> &x) const {
514     adv.assign(x.size(),static_cast<Real>(0));
515     adv[0] = static_cast<Real>(1);
516   }
517 
computeCoefficients(ROL::Ptr<Intrepid::FieldContainer<Real>> & kappa,ROL::Ptr<Intrepid::FieldContainer<Real>> & V) const518   void computeCoefficients(ROL::Ptr<Intrepid::FieldContainer<Real>> &kappa,
519                            ROL::Ptr<Intrepid::FieldContainer<Real>> &V) const {
520     // GET DIMENSIONS
521     int c = fe_vol_->gradN()->dimension(0);
522     int p = fe_vol_->gradN()->dimension(2);
523     int d = fe_vol_->gradN()->dimension(3);
524     std::vector<Real> pt(d), adv(d);
525     for (int i = 0; i < c; ++i) {
526       for (int j = 0; j < p; ++j) {
527         for ( int k = 0; k < d; ++k) {
528           pt[k] = (*fe_vol_->cubPts())(i,j,k);
529         }
530         // Compute diffusivity kappa
531         (*kappa)(i,j) = evaluateDiffusivity(pt);
532         // Compute advection velocity field V
533         evaluateVelocity(adv,pt);
534         for (int k = 0; k < d; ++k) {
535           (*V)(i,j,k) = adv[k];
536         }
537       }
538     }
539   }
540 
addControlOperator(ROL::Ptr<Intrepid::FieldContainer<Real>> & Bz,const ROL::Ptr<const std::vector<Real>> & z) const541   void addControlOperator(ROL::Ptr<Intrepid::FieldContainer<Real>> &Bz,
542                           const ROL::Ptr<const std::vector<Real>> &z) const {
543     // GET DIMENSIONS
544     int c = fe_vol_->gradN()->dimension(0);
545     int p = fe_vol_->gradN()->dimension(2);
546     int d = fe_vol_->gradN()->dimension(3);
547     std::vector<Real> pt(d);
548     Real xl(0), xu(0), yl(0), yu(0);
549     Bz->initialize();
550     for (int i = 0; i < c; ++i) {
551       for (int j = 0; j < p; ++j) {
552         for ( int k = 0; k < d; ++k) {
553           pt[k] = (*fe_vol_->cubPts())(i,j,k);
554         }
555         for (int l = 0; l < nx_; ++l) {
556           xl = XL_ + static_cast<Real>(l)*(XU_-XL_)/static_cast<Real>(nx_);
557           xu = XL_ + static_cast<Real>(l+1)*(XU_-XL_)/static_cast<Real>(nx_);
558           if ( pt[0] < xu && pt[0] >= xl ) {
559             for (int m = 0; m < ny_; ++m) {
560               int ind = l + m*nx_;
561               yl = YL_ + static_cast<Real>(m)*(YU_-YL_)/static_cast<Real>(ny_);
562               yu = YL_ + static_cast<Real>(m+1)*(YU_-YL_)/static_cast<Real>(ny_);
563               if ( pt[1] < yu && pt[1] >= yl ) {
564                 (*Bz)(i,j) -= (*z)[ind];
565               }
566             }
567           }
568         }
569       }
570     }
571   }
572 
addControlJaobian(ROL::Ptr<Intrepid::FieldContainer<Real>> & B,int l,int m) const573   void addControlJaobian(ROL::Ptr<Intrepid::FieldContainer<Real>> &B,
574                          int l, int m) const {
575     // GET DIMENSIONS
576     int c = fe_vol_->gradN()->dimension(0);
577     int p = fe_vol_->gradN()->dimension(2);
578     int d = fe_vol_->gradN()->dimension(3);
579     std::vector<Real> pt(d);
580     Real xl(0), xu(0), yl(0), yu(0);
581     xl = XL_ + static_cast<Real>(l)*(XU_-XL_)/static_cast<Real>(nx_);
582     xu = XL_ + static_cast<Real>(l+1)*(XU_-XL_)/static_cast<Real>(nx_);
583     yl = YL_ + static_cast<Real>(m)*(YU_-YL_)/static_cast<Real>(ny_);
584     yu = YL_ + static_cast<Real>(m+1)*(YU_-YL_)/static_cast<Real>(ny_);
585     int ind = l + m*nx_;
586     B->initialize();
587     for (int i = 0; i < c; ++i) {
588       for (int j = 0; j < p; ++j) {
589         for ( int k = 0; k < d; ++k) {
590           pt[k] = (*fe_vol_->cubPts())(i,j,k);
591         }
592         if ( pt[0] < xu && pt[0] >= xl && pt[1] < yu && pt[1] >= yl ) {
593           (*B)(i,j) = static_cast<Real>(-1);
594         }
595       }
596     }
597   }
598 
599 }; // PDE_stoch_adv_diff
600 
601 #endif
602