// @HEADER // ************************************************************************ // // Rapid Optimization Library (ROL) Package // Copyright (2014) Sandia Corporation // // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive // license for use of this work by or on behalf of the U.S. Government. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact lead developers: // Drew Kouri (dpkouri@sandia.gov) and // Denis Ridzal (dridzal@sandia.gov) // // ************************************************************************ // @HEADER /*! \file example_02.cpp \brief Shows how to solve the stochastic advection-diffusion problem. */ #include "Teuchos_Comm.hpp" #include "ROL_Stream.hpp" #include "Teuchos_GlobalMPISession.hpp" #include "Teuchos_XMLParameterListHelpers.hpp" #include "Tpetra_Core.hpp" #include "Tpetra_Version.hpp" #include #include //#include #include "ROL_Bounds.hpp" #include "ROL_Reduced_Objective_SimOpt.hpp" #include "ROL_MonteCarloGenerator.hpp" #include "ROL_OptimizationSolver.hpp" #include "ROL_TpetraTeuchosBatchManager.hpp" #include "../TOOLS/meshmanager.hpp" #include "../TOOLS/pdeconstraint.hpp" #include "../TOOLS/pdeobjective.hpp" #include "../TOOLS/pdevector.hpp" #include "../TOOLS/batchmanager.hpp" #include "pde_stoch_adv_diff.hpp" #include "obj_stoch_adv_diff.hpp" #include "mesh_stoch_adv_diff.hpp" typedef double RealT; template Real random(const Teuchos::Comm &comm, const Real a = -1, const Real b = 1) { Real val(0), u(0); if ( Teuchos::rank(comm)==0 ) { u = static_cast(rand())/static_cast(RAND_MAX); val = (b-a)*u + a; } Teuchos::broadcast(comm,0,1,&val); return val; } template void print(ROL::Objective &obj, const ROL::Vector &z, ROL::SampleGenerator &sampler, const ROL::Ptr > &comm, const std::string &filename) { Real tol(1e-8); int ngsamp = sampler.numGlobalSamples(); // Build objective function distribution int nsamp = sampler.numMySamples(); std::vector myvalues(nsamp), myzerovec(nsamp, 0); std::vector gvalues(ngsamp), gzerovec(ngsamp, 0); std::vector sample = sampler.getMyPoint(0); int sdim = sample.size(); std::vector > mysamples(sdim, myzerovec); std::vector > gsamples(sdim, gzerovec); for (int i = 0; i < nsamp; ++i) { sample = sampler.getMyPoint(i); obj.setParameter(sample); myvalues[i] = static_cast(obj.value(z,tol)); for (int j = 0; j < sdim; ++j) { mysamples[j][i] = static_cast(sample[j]); } } // Send data to root processor #ifdef HAVE_MPI ROL::Ptr > mpicomm = ROL::dynamicPtrCast >(comm); int nproc = Teuchos::size(*mpicomm); std::vector sampleCounts(nproc, 0), sampleDispls(nproc, 0); MPI_Gather(&nsamp,1,MPI_INT,&sampleCounts[0],1,MPI_INT,0,*(mpicomm->getRawMpiComm())()); for (int i = 1; i < nproc; ++i) { sampleDispls[i] = sampleDispls[i-1] + sampleCounts[i-1]; } MPI_Gatherv(&myvalues[0],nsamp,MPI_DOUBLE,&gvalues[0],&sampleCounts[0],&sampleDispls[0],MPI_DOUBLE,0,*(mpicomm->getRawMpiComm())()); for (int j = 0; j < sdim; ++j) { MPI_Gatherv(&mysamples[j][0],nsamp,MPI_DOUBLE,&gsamples[j][0],&sampleCounts[0],&sampleDispls[0],MPI_DOUBLE,0,*(mpicomm->getRawMpiComm())()); } #else gvalues.assign(myvalues.begin(),myvalues.end()); for (int j = 0; j < sdim; ++j) { gsamples[j].assign(mysamples[j].begin(),mysamples[j].end()); } #endif // Print int rank = Teuchos::rank(*comm); if ( rank==0 ) { std::ofstream file; file.open(filename); file << std::scientific << std::setprecision(15); for (int i = 0; i < ngsamp; ++i) { for (int j = 0; j < sdim; ++j) { file << std::setw(25) << std::left << gsamples[j][i]; } file << std::setw(25) << std::left << gvalues[i] << std::endl; } file.close(); } } template void printSampler(ROL::SampleGenerator &sampler, const ROL::Ptr > &comm, const std::string &filename) { int ngsamp = sampler.numGlobalSamples(); // Build objective function distribution int nsamp = sampler.numMySamples(); std::vector myzerovec(nsamp, 0); std::vector gzerovec(ngsamp, 0); std::vector sample = sampler.getMyPoint(0); int sdim = sample.size(); std::vector > mysamples(sdim, myzerovec); std::vector > gsamples(sdim, gzerovec); for (int i = 0; i < nsamp; ++i) { sample = sampler.getMyPoint(i); for (int j = 0; j < sdim; ++j) { mysamples[j][i] = static_cast(sample[j]); } } // Send data to root processor #ifdef HAVE_MPI ROL::Ptr > mpicomm = ROL::dynamicPtrCast >(comm); int nproc = Teuchos::size(*mpicomm); std::vector sampleCounts(nproc, 0), sampleDispls(nproc, 0); MPI_Gather(&nsamp,1,MPI_INT,&sampleCounts[0],1,MPI_INT,0,*(mpicomm->getRawMpiComm())()); for (int i = 1; i < nproc; ++i) { sampleDispls[i] = sampleDispls[i-1] + sampleCounts[i-1]; } for (int j = 0; j < sdim; ++j) { MPI_Gatherv(&mysamples[j][0],nsamp,MPI_DOUBLE,&gsamples[j][0],&sampleCounts[0],&sampleDispls[0],MPI_DOUBLE,0,*(mpicomm->getRawMpiComm())()); } #else for (int j = 0; j < sdim; ++j) { gsamples[j].assign(mysamples[j].begin(),mysamples[j].end()); } #endif // Print int rank = Teuchos::rank(*comm); if ( rank==0 ) { std::ofstream file; file.open(filename); file << std::scientific << std::setprecision(15); for (int i = 0; i < ngsamp; ++i) { for (int j = 0; j < sdim; ++j) { file << std::setw(25) << std::left << gsamples[j][i]; } file << std::endl; } file.close(); } } int main(int argc, char *argv[]) { // feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. int iprint = argc - 1; ROL::Ptr outStream; ROL::nullstream bhs; // outputs nothing /*** Initialize communicator. ***/ Teuchos::GlobalMPISession mpiSession (&argc, &argv, &bhs); ROL::Ptr > comm = Tpetra::getDefaultComm(); ROL::Ptr > serial_comm = ROL::makePtr>(); const int myRank = comm->getRank(); if ((iprint > 0) && (myRank == 0)) { outStream = ROL::makePtrFromRef(std::cout); } else { outStream = ROL::makePtrFromRef(bhs); } int errorFlag = 0; // *** Example body. try { /*** Read in XML input ***/ std::string filename = "input.xml"; Teuchos::RCP parlist = Teuchos::rcp( new Teuchos::ParameterList() ); Teuchos::updateParametersFromXmlFile( filename, parlist.ptr() ); // Problem dimensions const int controlDim = 9, stochDim = 37; const RealT one(1); /*************************************************************************/ /***************** BUILD GOVERNING PDE ***********************************/ /*************************************************************************/ /*** Initialize main data structure. ***/ ROL::Ptr > meshMgr = ROL::makePtr>(*parlist); // Initialize PDE describing advection-diffusion equation ROL::Ptr > pde = ROL::makePtr>(*parlist); ROL::Ptr > con = ROL::makePtr>(pde,meshMgr,serial_comm,*parlist,*outStream); ROL::Ptr > pdeCon = ROL::dynamicPtrCast >(con); pdeCon->getAssembler()->printMeshData(*outStream); con->setSolveParameters(*parlist); /*************************************************************************/ /***************** BUILD VECTORS *****************************************/ /*************************************************************************/ ROL::Ptr > u_ptr = pdeCon->getAssembler()->createStateVector(); ROL::Ptr > p_ptr = pdeCon->getAssembler()->createStateVector(); ROL::Ptr > du_ptr = pdeCon->getAssembler()->createStateVector(); u_ptr->randomize(); //u_ptr->putScalar(static_cast(1)); p_ptr->randomize(); //p_ptr->putScalar(static_cast(1)); du_ptr->randomize(); //du_ptr->putScalar(static_cast(0)); ROL::Ptr > up = ROL::makePtr>(u_ptr,pde,pdeCon->getAssembler()); ROL::Ptr > pp = ROL::makePtr>(p_ptr,pde,pdeCon->getAssembler()); ROL::Ptr > dup = ROL::makePtr>(du_ptr,pde,pdeCon->getAssembler()); // Create residual vectors ROL::Ptr > r_ptr = pdeCon->getAssembler()->createResidualVector(); r_ptr->randomize(); //r_ptr->putScalar(static_cast(1)); ROL::Ptr > rp = ROL::makePtr>(r_ptr,pde,pdeCon->getAssembler()); // Create control vector and set to ones ROL::Ptr > z_ptr = ROL::makePtr>(controlDim); ROL::Ptr > dz_ptr = ROL::makePtr>(controlDim); ROL::Ptr > yz_ptr = ROL::makePtr>(controlDim); // Create control direction vector and set to random for (int i = 0; i < controlDim; ++i) { (*z_ptr)[i] = random(*comm); (*dz_ptr)[i] = random(*comm); (*yz_ptr)[i] = random(*comm); } ROL::Ptr > zp = ROL::makePtr>(ROL::makePtr>(z_ptr)); ROL::Ptr > dzp = ROL::makePtr>(ROL::makePtr>(dz_ptr)); ROL::Ptr > yzp = ROL::makePtr>(ROL::makePtr>(yz_ptr)); // Create ROL SimOpt vectors ROL::Vector_SimOpt x(up,zp); ROL::Vector_SimOpt d(dup,dzp); ROL::Ptr > dualu_ptr = pdeCon->getAssembler()->createStateVector(); ROL::Ptr > dualup = ROL::makePtr>(dualu_ptr,pde,pdeCon->getAssembler()); /*************************************************************************/ /***************** BUILD COST FUNCTIONAL *********************************/ /*************************************************************************/ std::vector > > qoi_vec(2,ROL::nullPtr); qoi_vec[0] = ROL::makePtr>(pde->getFE()); qoi_vec[1] = ROL::makePtr>(); RealT stateCost = parlist->sublist("Problem").get("State Cost",1.e5); RealT controlCost = parlist->sublist("Problem").get("Control Cost",1.e0); std::vector wts = {stateCost, controlCost}; ROL::Ptr > obj = ROL::makePtr>(qoi_vec,wts,pdeCon->getAssembler()); bool storage = parlist->sublist("Problem").get("Use State and Adjoint Storage",true); ROL::Ptr > objReduced = ROL::makePtr>(obj, con, up, zp, pp, storage, false); /*************************************************************************/ /***************** BUILD BOUND CONSTRAINT ********************************/ /*************************************************************************/ ROL::Ptr > zlo_ptr = ROL::makePtr>(controlDim,0); ROL::Ptr > zhi_ptr = ROL::makePtr>(controlDim,1); ROL::Ptr > zlop = ROL::makePtr>(ROL::makePtr>(zlo_ptr)); ROL::Ptr > zhip = ROL::makePtr>(ROL::makePtr>(zhi_ptr)); ROL::Ptr > bnd = ROL::makePtr>(zlop,zhip); /*************************************************************************/ /***************** BUILD SAMPLER *****************************************/ /*************************************************************************/ int nsamp = parlist->sublist("Problem").get("Number of Samples",100); std::vector tmp = {-one,one}; std::vector > bounds(stochDim,tmp); ROL::Ptr > bman = ROL::makePtr>(comm); ROL::Ptr > sampler = ROL::makePtr>(nsamp,bounds,bman); /*************************************************************************/ /***************** BUILD STOCHASTIC PROBLEM ******************************/ /*************************************************************************/ ROL::OptimizationProblem opt(objReduced,zp,bnd); parlist->sublist("SOL").set("Initial Statistic",one); opt.setStochasticObjective(*parlist,sampler); /*************************************************************************/ /***************** RUN VECTOR AND DERIVATIVE CHECKS **********************/ /*************************************************************************/ bool checkDeriv = parlist->sublist("Problem").get("Check Derivatives",false); if ( checkDeriv ) { up->checkVector(*pp,*dup,true,*outStream); zp->checkVector(*yzp,*dzp,true,*outStream); std::vector param(stochDim,0); objReduced->setParameter(param); *outStream << "\n\nCheck Gradient of Full Objective Function\n"; obj->checkGradient(x,d,true,*outStream); *outStream << "\n\nCheck Hessian of Full Objective Function\n"; obj->checkHessVec(x,d,true,*outStream); *outStream << "\n\nCheck Full Jacobian of PDE Constraint\n"; con->checkApplyJacobian(x,d,*rp,true,*outStream); *outStream << "\n\nCheck Jacobian_1 of PDE Constraint\n"; con->checkApplyJacobian_1(*up,*zp,*dup,*rp,true,*outStream); *outStream << "\n\nCheck Jacobian_2 of PDE Constraint\n"; con->checkApplyJacobian_2(*up,*zp,*dzp,*rp,true,*outStream); *outStream << "\n\nCheck Full Hessian of PDE Constraint\n"; con->checkApplyAdjointHessian(x,*pp,d,x,true,*outStream); *outStream << "\n\nCheck Hessian_11 of PDE Constraint\n"; con->checkApplyAdjointHessian_11(*up,*zp,*pp,*dup,*dualup,true,*outStream); *outStream << "\n\nCheck Hessian_21 of PDE Constraint\n"; con->checkApplyAdjointHessian_21(*up,*zp,*pp,*dzp,*dualup,true,*outStream); *outStream << "\n\nCheck Hessian_12 of PDE Constraint\n"; con->checkApplyAdjointHessian_12(*up,*zp,*pp,*dup,*dzp,true,*outStream); *outStream << "\n\nCheck Hessian_22 of PDE Constraint\n"; con->checkApplyAdjointHessian_22(*up,*zp,*pp,*dzp,*dzp,true,*outStream); *outStream << "\n"; con->checkAdjointConsistencyJacobian(*dup,d,x,true,*outStream); *outStream << "\n"; con->checkInverseJacobian_1(*up,*up,*up,*zp,true,*outStream); *outStream << "\n"; *outStream << "\n\nCheck Gradient of Reduced Objective Function\n"; objReduced->checkGradient(*zp,*dzp,true,*outStream); *outStream << "\n\nCheck Hessian of Reduced Objective Function\n"; objReduced->checkHessVec(*zp,*dzp,true,*outStream); opt.check(*outStream); } /*************************************************************************/ /***************** SOLVE OPTIMIZATION PROBLEM ****************************/ /*************************************************************************/ parlist->sublist("Step").set("Type","Trust Region"); ROL::OptimizationSolver solver(opt,*parlist); zp->zero(); std::clock_t timer = std::clock(); solver.solve(*outStream); *outStream << "Optimization time: " << static_cast(std::clock()-timer)/static_cast(CLOCKS_PER_SEC) << " seconds." << std::endl << std::endl; /*************************************************************************/ /***************** OUTPUT RESULTS ****************************************/ /*************************************************************************/ std::clock_t timer_print = std::clock(); // Output control to file if ( myRank == 0 ) { std::ofstream zfile; zfile.open("control.txt"); for (int i = 0; i < controlDim; i++) { zfile << std::scientific << std::setprecision(15); zfile << (*z_ptr)[i] << std::endl; } zfile.close(); } // Output statisitic to file std::vector stat = opt.getObjectiveStatistic(); if ( myRank == 0 && stat.size() > 0 ) { std::ofstream sfile; sfile.open("stat.txt"); for (int i = 0; i < static_cast(stat.size()); ++i) { sfile << std::scientific << std::setprecision(15); sfile << stat[i] << std::endl; } } // Output expected state and samples to file up->zero(); pp->zero(); dup->zero(); RealT tol(1.e-8); ROL::Ptr > bman_Eu = ROL::makePtr>(comm); std::vector sample(stochDim); for (int i = 0; i < sampler->numMySamples(); ++i) { sample = sampler->getMyPoint(i); con->setParameter(sample); con->solve(*rp,*dup,*zp,tol); up->axpy(sampler->getMyWeight(i),*dup); } bman_Eu->sumAll(*up,*pp); pdeCon->getAssembler()->outputTpetraVector(p_ptr,"mean_state.txt"); // Print samples printSampler(*sampler,comm,"samples.txt"); // Build objective function distribution int nsamp_dist = parlist->sublist("Problem").get("Number of Output Samples",100); ROL::Ptr > sampler_dist = ROL::makePtr>(nsamp_dist,bounds,bman); print(*objReduced,*zp,*sampler_dist,comm,"obj_samples.txt"); *outStream << "Output time: " << static_cast(std::clock()-timer_print)/static_cast(CLOCKS_PER_SEC) << " seconds." << std::endl << std::endl; Teuchos::Array res(1,0); pdeCon->solve(*rp,*up,*zp,tol); r_ptr->norm2(res.view(0,1)); /*************************************************************************/ /***************** CHECK RESIDUAL NORM ***********************************/ /*************************************************************************/ *outStream << "Residual Norm: " << res[0] << std::endl << std::endl; errorFlag += (res[0] > 1.e-6 ? 1 : 0); } catch (std::logic_error& err) { *outStream << err.what() << "\n"; errorFlag = -1000; }; // end try if (errorFlag != 0) std::cout << "End Result: TEST FAILED\n"; else std::cout << "End Result: TEST PASSED\n"; return 0; }