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 example_01.cpp
45 \brief Shows how to solve a semilinear parabolic problem.
46 */
47
48 #include "Teuchos_Comm.hpp"
49 #include "Teuchos_GlobalMPISession.hpp"
50 #include "Teuchos_FancyOStream.hpp"
51
52 #include "Tpetra_Core.hpp"
53 #include "Tpetra_Version.hpp"
54
55 #include <iostream>
56 #include <algorithm>
57 #include <numeric>
58
59 #include <sys/types.h>
60 #include <unistd.h>
61
62 #include "ROL_Bounds.hpp"
63 #include "ROL_Stream.hpp"
64 #include "ROL_ParameterList.hpp"
65 #include "ROL_OptimizationSolver.hpp"
66 #include "ROL_ReducedDynamicObjective.hpp"
67 #include "ROL_RandomVector.hpp"
68 #include "ROL_DynamicConstraintCheck.hpp"
69 #include "ROL_DynamicObjectiveCheck.hpp"
70 #include "ROL_PinTConstraint.hpp"
71 #include "ROL_PinTVectorCommunication.hpp"
72 #include "ROL_PinTVectorCommunication_Tpetra.hpp"
73 #include "ROL_PinTVectorCommunication_StdTpetraComposite.hpp"
74
75 #include "../../TOOLS/dynconstraint.hpp"
76 #include "../../TOOLS/pdeobjective.hpp"
77 #include "../../TOOLS/ltiobjective.hpp"
78 #include "../../TOOLS/meshmanager.hpp"
79 #include "../../TOOLS/pdevector.hpp"
80 #include "dynpde_semilinear.hpp"
81 #include "obj_semilinear.hpp"
82
83 using RealT = double;
84
85 class KKTOperator : public ROL::LinearOperator<RealT> {
86 public:
87 ROL::Ptr<ROL::PinTConstraint<RealT>> pint_con;
88 ROL::Ptr<ROL::Vector<RealT>> state;
89 ROL::Ptr<ROL::Vector<RealT>> control;
90 int myRank;
91 ROL::Ptr<std::ostream> outStream;
92
apply(ROL::Vector<RealT> & Hv,const ROL::Vector<RealT> & v,RealT & tol) const93 void apply( ROL::Vector<RealT> &Hv, const ROL::Vector<RealT> &v, RealT &tol ) const override
94 {
95 pint_con->applyAugmentedKKT(Hv,v,*state,*control,tol);
96 }
97 };
98
99 class MGRITKKTOperator : public ROL::LinearOperator<RealT> {
100 public:
101 ROL::Ptr<ROL::PinTConstraint<RealT>> pint_con;
102 ROL::Ptr<ROL::Vector<RealT>> state;
103 ROL::Ptr<ROL::Vector<RealT>> control;
104 int myRank;
105 ROL::Ptr<std::ostream> outStream;
106
apply(ROL::Vector<RealT> & Hv,const ROL::Vector<RealT> & v,RealT & tol) const107 void apply( ROL::Vector<RealT> &Hv, const ROL::Vector<RealT> &v, RealT &tol ) const override
108 {
109 assert(false);
110 pint_con->applyMultigridAugmentedKKT(Hv,v,*state,*control,tol);
111 }
applyInverse(ROL::Vector<RealT> & Hv,const ROL::Vector<RealT> & v,RealT & tol) const112 void applyInverse( ROL::Vector<RealT> &Hv, const ROL::Vector<RealT> &v, RealT &tol ) const override
113 {
114 pint_con->applyMultigridAugmentedKKT(Hv,v,*state,*control,tol);
115 }
116 };
117
118 class WathenKKTOperator : public ROL::LinearOperator<RealT> {
119 public:
120 ROL::Ptr<ROL::PinTConstraint<RealT>> pint_con;
121 ROL::Ptr<ROL::Vector<RealT>> state;
122 ROL::Ptr<ROL::Vector<RealT>> control;
123 int myRank;
124 ROL::Ptr<std::ostream> outStream;
125
apply(ROL::Vector<RealT> & Hv,const ROL::Vector<RealT> & v,RealT & tol) const126 void apply( ROL::Vector<RealT> &Hv, const ROL::Vector<RealT> &v, RealT &tol ) const override
127 {
128 assert(false);
129 }
applyInverse(ROL::Vector<RealT> & Hv,const ROL::Vector<RealT> & v,RealT & tol) const130 void applyInverse( ROL::Vector<RealT> &Hv, const ROL::Vector<RealT> &v, RealT &tol ) const override
131 {
132 pint_con->applyWathenInverse(Hv,v,*state,*control,tol,false,0);
133 }
134 };
135
pauseToAttach(MPI_Comm mpicomm)136 inline void pauseToAttach(MPI_Comm mpicomm)
137 {
138 Teuchos::RCP<Teuchos::Comm<int> > comm =
139 Teuchos::createMpiComm<int>(Teuchos::rcp(new Teuchos::OpaqueWrapper<MPI_Comm>(mpicomm)));
140 Teuchos::FancyOStream out(Teuchos::rcpFromRef(std::cout));
141 out.setShowProcRank(true);
142 out.setOutputToRootOnly(-1);
143
144 comm->barrier();
145
146 // try to get them to print out all at once
147 out << "PID = " << getpid() << std::endl;
148
149 if (comm->getRank() == 0)
150 getchar();
151 comm->barrier();
152 }
153
154 ROL::Ptr<ROL::Vector<RealT>>
155 solveKKTSystem(const std::string & prefix,
156 bool useWathenPrec,int myRank,
157 double absTol,double relTol,
158 const Teuchos::RCP<Teuchos::StackedTimer> & timer,
159 const ROL::Ptr<std::ostream> & outStream,
160 const ROL::Ptr<ROL::PinTConstraint<RealT>> & pint_con,
161 const ROL::Ptr<ROL::Vector<RealT>> & kkt_b,
162 const ROL::Ptr<ROL::PinTVector<RealT>> & state,
163 const ROL::Ptr<ROL::PinTVector<RealT>> & control);
164
main(int argc,char * argv[])165 int main(int argc, char *argv[])
166 {
167
168 using Teuchos::RCP;
169
170 /*** Initialize communicator. ***/
171 Teuchos::GlobalMPISession mpiSession(&argc, &argv);
172
173 // pauseToAttach(MPI_COMM_WORLD);
174
175 ROL::Ptr<const Teuchos::Comm<int> > comm = Tpetra::getDefaultComm();
176
177 // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided.
178 const int myRank = comm->getRank();
179 ROL::Ptr<std::ostream> outStream = ROL::makeStreamPtr( std::cout, (argc > 1) && (myRank==0) );
180
181 int errorFlag = 0;
182
183 // *** Example body.
184 try {
185
186 /*** Read in XML input ***/
187 ROL::Ptr<ROL::ParameterList> parlist = ROL::getParametersFromXmlFile("input_ex01.xml");
188 int nt = parlist->sublist("Time Discretization").get("Number of Time Steps", 100);
189 RealT T = parlist->sublist("Time Discretization").get("End Time", 1.0);
190 RealT dt = T/static_cast<RealT>(nt);
191
192 const Teuchos::ParameterList & geomlist = parlist->sublist("Geometry");
193 RealT dx = geomlist.get<double>("Width") / geomlist.get<int>("NX");
194 RealT dy = geomlist.get<double>("Height") / geomlist.get<int>("NY");
195
196 // Add MGRIT parameter list stuff
197 int sweeps = parlist->get("MGRIT Sweeps", 1);
198 RealT omega = parlist->get("MGRIT Relaxation",2.0/3.0);
199 int coarseSweeps = parlist->get("MGRIT Coarse Sweeps", 1);
200 RealT coarseOmega = parlist->get("MGRIT Coarse Relaxation",1.0);
201 int numLevels = parlist->get("MGRIT Levels",3);
202 double relTol = parlist->get("MGRIT Krylov Relative Tolerance",1e-4);
203 double absTol = parlist->get("MGRIT Krylov Absolute Tolerance",1e-4);
204 int spaceProc = parlist->get("MGRIT Spatial Procs",1);
205 double globalScale = parlist->get("MGRIT Global Scale",1.0);
206 bool rebalance = parlist->get("MGRIT Rebalance",false);
207 int cgIterations = parlist->get("MGRIT CG Iterations",1);
208 double cntrlRegPar = parlist->get("MGRIT Control Regularization Parameter",1.0);
209
210 ROL::Ptr<const ROL::PinTCommunicators> communicators = ROL::makePtr<ROL::PinTCommunicators>(MPI_COMM_WORLD,spaceProc);
211 ROL::Ptr<const Teuchos::Comm<int>> mpiSpaceComm = ROL::makePtr<Teuchos::MpiComm<int>>(communicators->getSpaceCommunicator());
212
213 // for "serial" in time cases, use the wathen preconditioner
214 bool useWathenPrec = communicators->getTimeSize()==spaceProc;
215
216 /*************************************************************************/
217 /***************** BUILD GOVERNING PDE ***********************************/
218 /*************************************************************************/
219 /*** Initialize mesh data structure. ***/
220 ROL::Ptr<MeshManager<RealT>> meshMgr
221 = ROL::makePtr<MeshManager_Rectangle<RealT>>(*parlist);
222 // Initialize PDE describe semilinear equation
223 ROL::Ptr<DynamicPDE_Semilinear<RealT>> pde
224 = ROL::makePtr<DynamicPDE_Semilinear<RealT>>(*parlist);
225
226 /*************************************************************************/
227 /***************** BUILD CONSTRAINT **************************************/
228 /*************************************************************************/
229 ROL::Ptr<DynConstraint<RealT> > dyn_con
230 = ROL::makePtr<DynConstraint<RealT>>(pde,meshMgr,mpiSpaceComm,*parlist,*outStream);
231 const ROL::Ptr<Assembler<RealT>> assembler = dyn_con->getAssembler();
232 dyn_con->setSolveParameters(*parlist);
233 dyn_con->getAssembler()->printMeshData(*outStream);
234
235 /*************************************************************************/
236 /***************** BUILD VECTORS *****************************************/
237 /*************************************************************************/
238 ROL::Ptr<Tpetra::MultiVector<>> u0_ptr = assembler->createStateVector();
239 ROL::Ptr<Tpetra::MultiVector<>> zk_ptr = assembler->createControlVector();
240 ROL::Ptr<ROL::Vector<RealT>> u0, zk;
241 u0 = ROL::makePtr<PDE_PrimalSimVector<RealT>>(u0_ptr,pde,*assembler,*parlist);
242 zk = ROL::makePtr<PDE_PrimalOptVector<RealT>>(zk_ptr,pde,*assembler,*parlist);
243
244 // ROL::Ptr<const ROL::PinTVectorCommunication<RealT>> vectorComm = ROL::makePtr<ROL::PinTVectorCommunication_Tpetra<RealT>>();
245 ROL::Ptr<const ROL::PinTVectorCommunication<RealT>> vectorComm = ROL::makePtr<ROL::PinTVectorCommunication_StdTpetraComposite<RealT>>();
246 ROL::Ptr<ROL::PinTVector<RealT>> state = ROL::buildStatePinTVector<RealT>( communicators, vectorComm, nt, u0); // for Euler, Crank-Nicolson, stencil = [-1,0]
247 ROL::Ptr<ROL::PinTVector<RealT>> control = ROL::buildControlPinTVector<RealT>( communicators, vectorComm, nt, zk); // time discontinous, stencil = [0]
248
249 // make sure we are globally consistent
250 state->boundaryExchange();
251 control->boundaryExchange();
252
253 ROL::Ptr<ROL::Vector<RealT>> kkt_vector = ROL::makePtr<ROL::PartitionedVector<RealT>>({state->clone(),control->clone(),state->clone()});
254
255 /*************************************************************************/
256 /***************** BUILD PINT CONSTRAINT *********************************/
257 /*************************************************************************/
258
259 /*************************************************************************/
260 /************************* BUILD TIME STAMP ******************************/
261 /*************************************************************************/
262 auto timeStamp = ROL::makePtr<std::vector<ROL::TimeStamp<RealT>>>(control->numOwnedSteps());
263
264 double myFinalTime = dt*timeStamp->size();
265 double timeOffset = 0.0;
266 MPI_Exscan(&myFinalTime,&timeOffset,1,MPI_DOUBLE,MPI_SUM,communicators->getTimeCommunicator());
267
268 for( uint k=0; k<timeStamp->size(); ++k ) {
269 timeStamp->at(k).t.resize(2);
270 timeStamp->at(k).t.at(0) = k*dt+timeOffset;
271 timeStamp->at(k).t.at(1) = (k+1)*dt+timeOffset;
272 }
273
274 if(myRank==0) {
275 (*outStream) << "Sweeps = " << sweeps << std::endl;
276 (*outStream) << "Omega = " << omega << std::endl;
277 (*outStream) << "Levels = " << numLevels << std::endl;
278 (*outStream) << "Coarse Sweeps = " << coarseSweeps << std::endl;
279 (*outStream) << "Coarse Omega = " << coarseOmega << std::endl;
280 (*outStream) << "Global Scale = " << globalScale << std::endl;
281 (*outStream) << "Rebalance = " << rebalance << std::endl;
282 (*outStream) << "CG Iterations = " << cgIterations;
283 if(cgIterations==0)
284 *(outStream) << " (apply Wathen smoothing)" << std::endl;
285 else
286 *(outStream) << " (apply CG fix to Wathen smoothing)" << std::endl;
287 (*outStream) << "Cntrl Reg Par = " << cntrlRegPar << std::endl;
288 }
289
290 // build the parallel in time constraint from the user constraint
291 ROL::Ptr<ROL::PinTConstraint<RealT>> pint_con = ROL::makePtr<ROL::PinTConstraint<RealT>>(dyn_con,u0,timeStamp);
292 pint_con->applyMultigrid(numLevels,communicators,vectorComm,rebalance);
293 pint_con->setSweeps(sweeps);
294 pint_con->setRelaxation(omega);
295 pint_con->setCoarseSweeps(coarseSweeps);
296 pint_con->setCoarseRelaxation(coarseOmega);
297 pint_con->setGlobalScale(globalScale);
298 pint_con->setCGIterations(cgIterations);
299 pint_con->setControlRegParam(cntrlRegPar);
300 pint_con->setRecordResidualReductions(true);
301
302 /*************************************************************************/
303 /***************** Run KKT Solver ***************************************/
304 /*************************************************************************/
305
306 Teuchos::RCP<Teuchos::StackedTimer> timer = Teuchos::TimeMonitor::getStackedTimer();
307 double tol = 1e-12;
308
309 state->setScalar(1.0);
310 control->setScalar(1.0);
311
312 // setup and solve the lagrange multiplier RHS of the SQP algorithm
313 ///////////////////////////////////////////////////////////////////////////
314 {
315 auto kkt_b = kkt_vector->clone();
316 kkt_b->setScalar(1.0);
317 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(0)->scale(dt*dx*dy); // u
318 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(1)->scale(dt*dx*dy); // z
319 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(2)->scale(0.0); // lambda
320
321 if(myRank==0) (*outStream) << std::endl;
322
323 solveKKTSystem("LAGR MULTIPLIER STEP: ",
324 useWathenPrec,myRank,absTol,relTol,
325 timer,outStream,
326 pint_con,kkt_b,state,control);
327
328 if(myRank==0) (*outStream) << std::endl;
329 }
330
331 // compute quasi normal step
332 ///////////////////////////////////////////////////////////////////////////
333
334 ROL::Ptr<ROL::Vector<RealT>> g_k; // this will be use in tangential step
335 {
336 ROL::Ptr<ROL::Vector<RealT>> residual = state->clone();
337 ROL::Ptr<ROL::Vector<RealT>> cau_pt_1;
338 ROL::Ptr<ROL::Vector<RealT>> cau_pt_2;
339
340 // residual = c(x_k)
341 pint_con->value(*residual,*state,*control,tol );
342
343 {
344 ROL::Ptr<ROL::Vector<RealT>> jv_1 = state->clone();
345 ROL::Ptr<ROL::Vector<RealT>> jv_2 = state->clone();
346 ROL::Ptr<ROL::Vector<RealT>> ajv_1 = state->clone();
347 ROL::Ptr<ROL::Vector<RealT>> ajv_2 = control->clone();
348
349 // ajv = c'(x_k)^* c(x_k)
350 pint_con->applyAdjointJacobian_1(*ajv_1,*residual,*state,*control,tol);
351 pint_con->applyAdjointJacobian_2(*ajv_2,*residual,*state,*control,tol);
352
353 // jv = c'(x_k) c'(x_k)^* c(x_k)
354 pint_con->applyJacobian_1(*jv_1,*ajv_1,*state,*control,tol);
355 pint_con->applyJacobian_2(*jv_2,*ajv_2,*state,*control,tol);
356
357 RealT norm_ajv_sqr = std::pow(ajv_1->norm(),2.0) + std::pow(ajv_2->norm(),2.0);
358 RealT norm_jv_sqr = std::pow(jv_1->norm(),2.0) + std::pow(jv_2->norm(),2.0);
359
360 // now we we will modify the jacobian components
361 jv_1->scale(norm_ajv_sqr/norm_jv_sqr);
362 jv_2->scale(norm_ajv_sqr/norm_jv_sqr);
363 residual->plus(*jv_1);
364 residual->plus(*jv_2);
365
366 jv_1 = ROL::nullPtr;
367 jv_2 = ROL::nullPtr;
368
369 // cauchy point
370 cau_pt_1 = ajv_1; cau_pt_1->scale(norm_ajv_sqr/norm_jv_sqr);
371 cau_pt_2 = ajv_2; cau_pt_2->scale(norm_ajv_sqr/norm_jv_sqr);
372 }
373
374 // build RHS vector
375 auto kkt_b = kkt_vector->clone();
376 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(0)->set(*cau_pt_1); // u
377 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(1)->set(*cau_pt_2); // z
378 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(2)->set(*residual); // lambda
379
380 residual = ROL::nullPtr;
381
382 if(myRank==0) (*outStream) << std::endl;
383
384 auto delta_nk = solveKKTSystem("QUASI-NORMAL STEP: ",
385 useWathenPrec,myRank,absTol,relTol,
386 timer,outStream,
387 pint_con,kkt_b,state,control);
388
389 if(myRank==0) (*outStream) << std::endl;
390
391 kkt_b->setScalar(1.0);
392 kkt_b->plus(*delta_nk);
393
394 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(0)->scale(dt*dx*dy); // u
395 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(1)->scale(dt*dx*dy); // z
396 ROL::dynamicPtrCast<ROL::PartitionedVector<double>>(kkt_b)->get(2)->setScalar(0.0); // lambda
397
398 g_k = kkt_b;
399 }
400
401 // compute tangential step step
402 ///////////////////////////////////////////////////////////////////////////
403 {
404 if(myRank==0) (*outStream) << std::endl;
405
406 solveKKTSystem("TANG STEP: ",
407 useWathenPrec,myRank,absTol,relTol,
408 timer,outStream,
409 pint_con,g_k,state,control);
410
411 if(myRank==0) (*outStream) << std::endl;
412 }
413
414 // setup and solve the quasi normal step
415
416 #if 0
417 {
418 // This was useful for debugging, maintaing it so that we can recreate it if required.
419 // However, its not consistent right now so I don't want to mislead.
420
421 ROL::Ptr<ROL::Vector<RealT>> scratch;
422 {
423 /*************************************************************************/
424 /***************** BUILD SERIAL-IN-TIME CONSTRAINT ***********************/
425 /*************************************************************************/
426 auto serial_con = ROL::make_SerialConstraint(dyn_con, *u0, timeStamp);
427
428 /*************************************************************************/
429 /******************* BUILD SERIAL-IN-TIME VECTORS ************************/
430 /*************************************************************************/
431 auto U = ROL::PartitionedVector<RealT>::create(*uo, nt);
432 auto Z = ROL::PartitionedVector<RealT>::create(*zk, nt);
433 auto C = ROL::PartitionedVector<RealT>::create(*ck, nt);
434
435 scratch = U->clone(); // this will be used for testing in the PINT vector
436
437 auto UZ = ROL::make_Vector_SimOpt(U, Z);
438 auto X = UZ->clone();
439 auto V_x = X->clone();
440 auto V_c = C->clone();
441 auto V_l = C->dual().clone();
442 auto ajv = X->dual().clone();
443 auto ajvpx = X->dual().clone();
444 auto jv = C->clone();
445
446 /*************************************************************************/
447 /******************* APPLY AUGMENTED SYSTEM TO 1's ***********************/
448 /*************************************************************************/
449 X->zero();
450 ROL::dynamicPtrCast<ROL::Vector_SimOpt<RealT>>(V_x)->get_1()->setScalar(1.0);
451 ROL::dynamicPtrCast<ROL::Vector_SimOpt<RealT>>(V_x)->get_2()->setScalar(2.0);
452 V_l->setScalar(3.0);
453 ajvpx->set(V_x->dual());
454 serial_con->applyAdjointJacobian(*ajv, *V_l, *X, dummytol);
455 ajvpx->plus(*ajv);
456
457 auto ajv_u = ROL::dynamicPtrCast<ROL::Vector_SimOpt<RealT>>(ajv)->get_1();
458 auto ajv_z = ROL::dynamicPtrCast<ROL::Vector_SimOpt<RealT>>(ajv)->get_2();
459
460 serial_con->applyJacobian(*jv, *V_x, *X, dummytol);
461
462 (*outStream) << "\nSerial components of augmented system:\n";
463 (*outStream) << " Norm of Aug*1 1st component = " << ajvpx->norm() << "\n";
464 (*outStream) << " Norm of Aug*1 2nd component = " << jv->norm() << "\n";
465
466 auto Hv_u = ROL::dynamicPtrCast<ROL::Vector_SimOpt<RealT>>(ajvpx)->get_1();
467 auto Hv_z = ROL::dynamicPtrCast<ROL::Vector_SimOpt<RealT>>(ajvpx)->get_2();
468 auto Hv_l = jv;
469
470 (*outStream) << " Norm of Aug*1_u = " << Hv_u->norm() << "\n";
471 (*outStream) << " Norm of Aug*1_z = " << Hv_z->norm() << "\n";
472 (*outStream) << " Norm of Aug*1_l = " << Hv_l->norm() << "\n";
473
474 }
475 {
476 /*************************************************************************/
477 /************************* TEST THE PINT SYSTEM *************************/
478 /*************************************************************************/
479
480 /*************************************************************************/
481 /******************* BUILD PARALLEL-IN-TIME VECTORS **********************/
482 /*************************************************************************/
483 auto U = ROL::buildStatePinTVector<RealT>( communicators, vectorComm, nt, uo); // for Euler, Crank-Nicolson, stencil = [-1,0]
484 auto Z = ROL::buildControlPinTVector<RealT>(communicators, vectorComm, nt, zk); // time discontinous, stencil = [0]
485 auto C = ROL::buildStatePinTVector<RealT>( communicators, vectorComm, nt, ck); // for Euler, Crank-Nicolson, stencil = [-1,0]
486
487 auto triple = ROL::makePtr<ROL::PartitionedVector<RealT>>({U->clone(),Z->clone(),C->clone()});
488 auto V = triple->clone();
489 auto Hv = triple->dual().clone();
490
491 /*************************************************************************/
492 /******************* APPLY AUGMENTED SYSTEM TO 1's ***********************/
493 /*************************************************************************/
494
495 U->zero();
496 Z->zero();
497 ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(V)->get(0)->setScalar(1.0);
498 ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(V)->get(1)->setScalar(2.0);
499 ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(V)->get(2)->setScalar(3.0);
500 Hv->setScalar(0.0);
501
502 pint_con->applyAugmentedKKT(*Hv,*V,*U,*Z,tol);
503
504 auto Hv_u = ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(Hv)->get(0);
505 auto Hv_z = ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(Hv)->get(1);
506 auto Hv_l = ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(Hv)->get(2);
507
508 (*outStream) << "\nParallel compnents of augmented system:\n";
509 (*outStream) << " Norm of Aug*1_u = " << Hv_u->norm() << "\n";
510 (*outStream) << " Norm of Aug*1_z = " << Hv_z->norm() << "\n";
511 (*outStream) << " Norm of Aug*1_l = " << Hv_l->norm() << "\n";
512
513 auto pint_Hv_u = ROL::dynamicPtrCast<ROL::PinTVector<RealT>>(Hv_u);
514 auto part_scratch = ROL::dynamicPtrCast<ROL::PartitionedVector<RealT>>(scratch);
515 for(int i=0;i<pint_Hv_u->numOwnedSteps();i++) {
516
517 part_scratch->get(i)->setScalar(-1.0);
518 part_scratch->get(i)->axpy(1.0,*pint_Hv_u->getVectorPtr(2*i));
519 part_scratch->get(i)->axpy(1.0,*pint_Hv_u->getVectorPtr(2*i+1));
520 }
521
522 (*outStream) << " Norm of Aug*1_u modified = " << scratch->norm() << "\n";
523 }
524 }
525 #endif
526 }
527 catch (std::logic_error& err) {
528 *outStream << err.what() << "\n";
529 errorFlag = -1000;
530 }; // end try
531
532 if(myRank==0) {
533 if (errorFlag != 0)
534 std::cout << "End Result: TEST FAILED " << myRank << "\n";
535 else
536 std::cout << "End Result: TEST PASSED " << myRank << "\n";
537 }
538
539 return 0;
540 }
541
542 ROL::Ptr<ROL::Vector<RealT>>
solveKKTSystem(const std::string & prefix,bool useWathenPrec,int myRank,double absTol,double relTol,const Teuchos::RCP<Teuchos::StackedTimer> & timer,const ROL::Ptr<std::ostream> & outStream,const ROL::Ptr<ROL::PinTConstraint<RealT>> & pint_con,const ROL::Ptr<ROL::Vector<RealT>> & kkt_b,const ROL::Ptr<ROL::PinTVector<RealT>> & state,const ROL::Ptr<ROL::PinTVector<RealT>> & control)543 solveKKTSystem(const std::string & prefix,
544 bool useWathenPrec,int myRank,
545 double absTol,double relTol,
546 const Teuchos::RCP<Teuchos::StackedTimer> & timer,
547 const ROL::Ptr<std::ostream> & outStream,
548 const ROL::Ptr<ROL::PinTConstraint<RealT>> & pint_con,
549 const ROL::Ptr<ROL::Vector<RealT>> & kkt_b,
550 const ROL::Ptr<ROL::PinTVector<RealT>> & state,
551 const ROL::Ptr<ROL::PinTVector<RealT>> & control)
552 {
553 using Teuchos::RCP;
554
555 RealT res0 = kkt_b->norm();
556 res0 = kkt_b->norm();
557
558 auto kkt_x_out = kkt_b->clone();
559 kkt_x_out->zero();
560
561 KKTOperator kktOperator;
562 kktOperator.pint_con = pint_con;
563 kktOperator.state = state;
564 kktOperator.control = control;
565 kktOperator.outStream = outStream;
566 kktOperator.myRank = myRank;
567
568 RCP<ROL::LinearOperator<RealT>> precOperator;
569
570 // build the preconditioner
571 if(useWathenPrec) {
572 RCP<WathenKKTOperator> wathenOperator(new WathenKKTOperator);
573 wathenOperator->pint_con = pint_con;
574 wathenOperator->state = state;
575 wathenOperator->control = control;
576 wathenOperator->outStream = outStream;
577 wathenOperator->myRank = myRank;
578
579 precOperator = wathenOperator;
580 }
581 else {
582 RCP<MGRITKKTOperator> mgOperator(new MGRITKKTOperator);
583 mgOperator->pint_con = pint_con;
584 mgOperator->state = state;
585 mgOperator->control = control;
586 mgOperator->outStream = outStream;
587 mgOperator->myRank = myRank;
588
589 precOperator = mgOperator;
590 }
591
592 Teuchos::ParameterList parlist;
593 ROL::ParameterList &krylovList = parlist.sublist("General").sublist("Krylov");
594 krylovList.set("Absolute Tolerance",absTol);
595 krylovList.set("Relative Tolerance",relTol);
596
597 if(myRank==0)
598 (*outStream) << "Relative tolerance = " << relTol << std::endl;
599
600 ROL::GMRES<RealT> krylov(parlist); // TODO: Do Belos
601 // ROL::MINRES<RealT> krylov(1e0, 1e-6, 200); // TODO: Do Belos
602
603 int flag = 0;
604 int iter = 0;
605
606
607 if(myRank==0) {
608 (*outStream) << "Solving KKT system: ";
609 if(useWathenPrec)
610 (*outStream) << "using Wathen preconditioner" << std::endl;
611 else
612 (*outStream) << "using MGRIT preconditioner" << std::endl;
613 }
614
615 MPI_Barrier(MPI_COMM_WORLD);
616 double t0 = MPI_Wtime();
617
618 timer->start("krylov");
619 RealT finalTol = krylov.run(*kkt_x_out,kktOperator,*kkt_b,*precOperator,iter,flag);
620 timer->stop("krylov");
621
622 MPI_Barrier(MPI_COMM_WORLD);
623 double tf = MPI_Wtime();
624
625 // Don't trust residual computation, so repeat.
626 auto myb = kkt_b->clone();
627 myb->set(*kkt_b);
628 auto norm_myb = myb->norm();
629 auto tmp = kkt_b->clone();
630 RealT dummytol = 1e-8;
631 kktOperator.apply(*tmp, *kkt_x_out, dummytol);
632 tmp->axpy(-1, *myb);
633 auto norm_myAxmb = tmp->norm();
634 auto norm_mysoln = kkt_x_out->norm();
635
636 if(myRank==0) {
637 (*outStream) << prefix << "Krylov Iteration = " << iter << " " << (finalTol / res0) << " " << tf-t0 << std::endl;
638 (*outStream) << "||x||=" << norm_mysoln << " ||b||=" << norm_myb << " ||Ax-b||=" << norm_myAxmb << std::endl;
639
640 const std::map<int,std::vector<double>> & preSmooth = pint_con->getPreSmoothResidualReductions();
641 const std::map<int,std::vector<double>> & postSmooth = pint_con->getPostSmoothResidualReduction();
642 const std::vector<double> & coarseSmooth = pint_con->getCoarseResidualReduction();
643
644 if(not useWathenPrec) {
645 // loop over presmoother residual reductions
646 *outStream << "Presmooth Reductions: " << std::endl;
647 for(auto iter_l : preSmooth) {
648 double average = std::accumulate( iter_l.second.begin(), iter_l.second.end(), 0.0)/coarseSmooth.size();
649 double min = *std::min_element(iter_l.second.begin(),iter_l.second.end());
650 double max = *std::max_element(iter_l.second.begin(),iter_l.second.end());
651 *outStream << " level ";
652 *outStream << "min,avg,max = " << min << ", " << average << ", " << max << std::endl;
653 }
654
655 // loop over postsmoother residual reductions
656 *outStream << "Postsmooth Reductions: " << std::endl;
657 for(auto iter_l : postSmooth) {
658 double average = std::accumulate( iter_l.second.begin(), iter_l.second.end(), 0.0)/coarseSmooth.size();
659 double min = *std::min_element(iter_l.second.begin(),iter_l.second.end());
660 double max = *std::max_element(iter_l.second.begin(),iter_l.second.end());
661 *outStream << " level ";
662 *outStream << "min,avg,max = " << min << ", " << average << ", " << max << std::endl;
663 }
664
665 // loop over coarse residual reductions
666 {
667 *outStream << "Coarse Reductions: ";
668 double average = std::accumulate( coarseSmooth.begin(), coarseSmooth.end(), 0.0)/coarseSmooth.size();
669 double min = *std::min_element(coarseSmooth.begin(),coarseSmooth.end());
670 double max = *std::max_element(coarseSmooth.begin(),coarseSmooth.end());
671 *outStream << "min,avg,max = " << min << ", " << average << ", " << max << std::endl;
672 *outStream << std::endl;
673 }
674 }
675 }
676
677 pint_con->clearResidualReduction();
678
679 return kkt_x_out;
680 }
681