|
| 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 Solves a source inversion problem governed by the |
| 46 | + advection-diffusion equation. |
| 47 | +*/ |
| 48 | + |
| 49 | +#include "Teuchos_Comm.hpp" |
| 50 | +#include "Teuchos_GlobalMPISession.hpp" |
| 51 | +#include "Tpetra_Core.hpp" |
| 52 | +#include "Tpetra_Version.hpp" |
| 53 | + |
| 54 | +#include "ROL_Stream.hpp" |
| 55 | +#include "ROL_ParameterList.hpp" |
| 56 | +#include "ROL_Solver.hpp" |
| 57 | +#include "ROL_ReducedDynamicObjective.hpp" |
| 58 | +#include "ROL_Bounds.hpp" |
| 59 | +#include "ROL_DynamicConstraintCheck.hpp" |
| 60 | +#include "ROL_DynamicObjectiveCheck.hpp" |
| 61 | +#include "ROL_TypeBIndicatorObjective.hpp" |
| 62 | +#include <iostream> |
| 63 | +//#include <fenv.h> |
| 64 | + |
| 65 | +#include "../../TOOLS/meshmanager.hpp" |
| 66 | +#include "../../TOOLS/lindynconstraint.hpp" |
| 67 | +#include "../../TOOLS/ltiobjective.hpp" |
| 68 | +#include "../../TOOLS/pdevector.hpp" |
| 69 | +#include "../../TOOLS/pdeobjective.hpp" |
| 70 | +#include "dynpde_adv_diff.hpp" |
| 71 | +#include "obj_adv_diff.hpp" |
| 72 | +#include "mesh_adv_diff.hpp" |
| 73 | +#include "l1penaltydynamic.hpp" |
| 74 | + |
| 75 | +#include "ROL_TypeP_TrustRegionAlgorithm.hpp" |
| 76 | + |
| 77 | + |
| 78 | +int main(int argc, char *argv[]) { |
| 79 | +// feenableexcept(FE_DIVBYZERO | FE_INVALID | FE_OVERFLOW); |
| 80 | + |
| 81 | + using RealT = double; |
| 82 | + |
| 83 | + /*** Initialize communicator. ***/ |
| 84 | + Teuchos::GlobalMPISession mpiSession(&argc, &argv); |
| 85 | + ROL::Ptr<const Teuchos::Comm<int>> comm |
| 86 | + = Tpetra::getDefaultComm(); |
| 87 | + |
| 88 | + // This little trick lets us print to std::cout only if a (dummy) command-line argument is provided. |
| 89 | + const int myRank = comm->getRank(); |
| 90 | + ROL::Ptr<std::ostream> outStream = ROL::makeStreamPtr( std::cout, (argc > 1) && (myRank==0) ); |
| 91 | + |
| 92 | + int errorFlag = 0; |
| 93 | + |
| 94 | + // *** Example body. |
| 95 | + try { |
| 96 | + |
| 97 | + /*** Read in XML input ***/ |
| 98 | + ROL::Ptr<ROL::ParameterList> parlist = ROL::getParametersFromXmlFile("input.xml"); |
| 99 | + int nt = parlist->sublist("Time Discretization").get("Number of Time Steps", 100); |
| 100 | + RealT T = parlist->sublist("Time Discretization").get("End Time", 1.0); |
| 101 | + RealT dt = T/static_cast<RealT>(nt); |
| 102 | + int controlDim = 9; |
| 103 | + |
| 104 | + /*************************************************************************/ |
| 105 | + /***************** BUILD GOVERNING PDE ***********************************/ |
| 106 | + /*************************************************************************/ |
| 107 | + /*** Initialize main data structure. ***/ |
| 108 | + ROL::Ptr<MeshManager<RealT>> meshMgr |
| 109 | + = ROL::makePtr<MeshManager_adv_diff<RealT>>(*parlist); |
| 110 | + // Initialize PDE describing advection-diffusion equation |
| 111 | + ROL::Ptr<DynamicPDE_adv_diff<RealT>> pde |
| 112 | + = ROL::makePtr<DynamicPDE_adv_diff<RealT>>(*parlist); |
| 113 | + |
| 114 | + /*************************************************************************/ |
| 115 | + /***************** BUILD CONSTRAINT **************************************/ |
| 116 | + /*************************************************************************/ |
| 117 | + bool isLTI = !parlist->sublist("Problem").get("Time Varying Coefficients",false); |
| 118 | + ROL::Ptr<LinDynConstraint<RealT>> dyn_con |
| 119 | + = ROL::makePtr<LinDynConstraint<RealT>>(pde,meshMgr,comm,*parlist,isLTI,*outStream); |
| 120 | + dyn_con->getAssembler()->printMeshData(*outStream); |
| 121 | + |
| 122 | + /*************************************************************************/ |
| 123 | + /***************** BUILD STATE VECTORS ***********************************/ |
| 124 | + /*************************************************************************/ |
| 125 | + ROL::Ptr<Tpetra::MultiVector<>> u0_ptr, uo_ptr, un_ptr, ck_ptr; |
| 126 | + u0_ptr = dyn_con->getAssembler()->createStateVector(); |
| 127 | + uo_ptr = dyn_con->getAssembler()->createStateVector(); |
| 128 | + un_ptr = dyn_con->getAssembler()->createStateVector(); |
| 129 | + ck_ptr = dyn_con->getAssembler()->createResidualVector(); |
| 130 | + ROL::Ptr<ROL::Vector<RealT>> u0, uo, un, ck, zk; |
| 131 | + u0 = ROL::makePtr<PDE_PrimalSimVector<RealT>>(u0_ptr,pde,*dyn_con->getAssembler()); |
| 132 | + uo = ROL::makePtr<PDE_PrimalSimVector<RealT>>(uo_ptr,pde,*dyn_con->getAssembler()); |
| 133 | + un = ROL::makePtr<PDE_PrimalSimVector<RealT>>(un_ptr,pde,*dyn_con->getAssembler()); |
| 134 | + ck = ROL::makePtr<PDE_DualSimVector<RealT>>(ck_ptr,pde,*dyn_con->getAssembler()); |
| 135 | + zk = ROL::makePtr<PDE_OptVector<RealT>>(ROL::makePtr<ROL::StdVector<RealT>>(controlDim)); |
| 136 | + ROL::Ptr<ROL::PartitionedVector<RealT>> z |
| 137 | + = ROL::PartitionedVector<RealT>::create(*zk, nt); |
| 138 | + |
| 139 | + /*************************************************************************/ |
| 140 | + /***************** BUILD COST FUNCTIONAL *********************************/ |
| 141 | + /*************************************************************************/ |
| 142 | + std::vector<ROL::Ptr<QoI<RealT>>> qoi_vec(2,ROL::nullPtr); |
| 143 | + qoi_vec[0] = ROL::makePtr<QoI_State_Cost_adv_diff<RealT>>(pde->getFE()); |
| 144 | + qoi_vec[1] = ROL::makePtr<QoI_State_MY_adv_diff<RealT>>(pde->getFE()); |
| 145 | + RealT stateCost = parlist->sublist("Problem").get("State Cost",1e5); |
| 146 | + RealT myCost = 1e0; |
| 147 | + std::vector<RealT> wts = {stateCost, myCost}; |
| 148 | + ROL::Ptr<ROL::Objective_SimOpt<RealT>> obj_k |
| 149 | + = ROL::makePtr<PDE_Objective<RealT>>(qoi_vec,wts,dyn_con->getAssembler()); |
| 150 | + ROL::Ptr<LTI_Objective<RealT>> dyn_obj |
| 151 | + = ROL::makePtr<LTI_Objective<RealT>>(*parlist,obj_k,false); |
| 152 | + |
| 153 | + /*************************************************************************/ |
| 154 | + /***************** BUILD REDUCED COST FUNCTIONAL *************************/ |
| 155 | + /*************************************************************************/ |
| 156 | + std::vector<ROL::TimeStamp<RealT>> timeStamp(nt); |
| 157 | + for( int k=0; k<nt; ++k ) { |
| 158 | + timeStamp.at(k).t.resize(2); |
| 159 | + timeStamp.at(k).t.at(0) = k*dt; |
| 160 | + timeStamp.at(k).t.at(1) = (k+1)*dt; |
| 161 | + } |
| 162 | + ROL::ParameterList &rpl = parlist->sublist("Reduced Dynamic Objective"); |
| 163 | + ROL::Ptr<ROL::ReducedDynamicObjective<RealT>> obj |
| 164 | + = ROL::makePtr<ROL::ReducedDynamicObjective<RealT>>(dyn_obj, dyn_con, u0, zk, ck, timeStamp, rpl, outStream); |
| 165 | + |
| 166 | + /*************************************************************************/ |
| 167 | + /***************** BUILD BOUND CONSTRAINT AND L1 PENALTY *****************/ |
| 168 | + /*************************************************************************/ |
| 169 | + ROL::Ptr<ROL::PartitionedVector<RealT>> zlo = ROL::PartitionedVector<RealT>::create(*zk, nt); |
| 170 | + ROL::Ptr<ROL::PartitionedVector<RealT>> zhi = ROL::PartitionedVector<RealT>::create(*zk, nt); |
| 171 | + zlo->setScalar(-static_cast<RealT>(1)); zhi->setScalar(static_cast<RealT>(1)); |
| 172 | + ROL::Ptr<L1_Dyn_Objective<RealT>> nobj |
| 173 | + = ROL::makePtr<L1_Dyn_Objective<RealT>>(*parlist, timeStamp, zlo, zhi); |
| 174 | + |
| 175 | + /*************************************************************************/ |
| 176 | + /***************** RUN VECTOR AND DERIVATIVE CHECKS **********************/ |
| 177 | + /*************************************************************************/ |
| 178 | + bool checkDeriv = parlist->sublist("Problem").get("Check Derivatives",false); |
| 179 | + if ( checkDeriv ) { |
| 180 | + ROL::Ptr<ROL::PartitionedVector<RealT>> dz = ROL::PartitionedVector<RealT>::create(*zk, nt); |
| 181 | + ROL::Ptr<ROL::PartitionedVector<RealT>> hz = ROL::PartitionedVector<RealT>::create(*zk, nt); |
| 182 | + z->randomize(); dz->randomize(); hz->randomize(); |
| 183 | + zk->randomize(); uo->randomize(); un->randomize(); |
| 184 | + ROL::ValidateFunction<RealT> validate(1,13,20,11,true,*outStream); |
| 185 | + ROL::DynamicObjectiveCheck<RealT>::check(*dyn_obj,validate,*uo,*un,*zk,timeStamp[0]); |
| 186 | + ROL::DynamicConstraintCheck<RealT>::check(*dyn_con,validate,*uo,*un,*zk,timeStamp[0]); |
| 187 | + obj->checkGradient(*z,*dz,true,*outStream); |
| 188 | + obj->checkHessVec(*z,*dz,true,*outStream); |
| 189 | + obj->checkHessSym(*z,*dz,*hz,true,*outStream); |
| 190 | + } |
| 191 | + |
| 192 | + /*************************************************************************/ |
| 193 | + /***************** SOLVE OPTIMIZATION PROBLEM ****************************/ |
| 194 | + /*************************************************************************/ |
| 195 | + RealT gtol(1e-2), zerr(0), ztol0(1e-6), ztol(1); |
| 196 | + z->zero(); |
| 197 | + ROL::Ptr<ROL::Vector<RealT>> zprev = z->clone(), zdiff = z->clone(); |
| 198 | + ROL::Ptr<ROL::TypeP::TrustRegionAlgorithm<RealT>> algo; |
| 199 | + parlist->sublist("Status Test").set("Use Relative Tolerances",false); |
| 200 | + for (unsigned i = 0; i < 20; ++i) { |
| 201 | + *outStream << std::endl << "Moreau-Yosida Parameter: " |
| 202 | + << myCost << std::endl |
| 203 | + << "Gradient Tolerance: " |
| 204 | + << gtol << std::endl << std::endl; |
| 205 | + |
| 206 | + ztol = ztol0 / std::max(static_cast<RealT>(1),z->norm()); |
| 207 | + zprev->set(*z); |
| 208 | + parlist->sublist("Status Test").set("Gradient Tolerance",gtol); |
| 209 | + parlist->sublist("Status Test").set("Step Tolerance",static_cast<RealT>(1e-4)*gtol); |
| 210 | + algo = ROL::makePtr<ROL::TypeP::TrustRegionAlgorithm<RealT>>(*parlist); |
| 211 | + std::clock_t timer = std::clock(); |
| 212 | + algo->run(*z, *obj, *nobj, *outStream); |
| 213 | + *outStream << "Optimization time: " |
| 214 | + << static_cast<RealT>(std::clock()-timer)/static_cast<RealT>(CLOCKS_PER_SEC) |
| 215 | + << " seconds." << std::endl << std::endl; |
| 216 | + parlist->sublist("Reduced Dynamic Objective").set("State Rank", static_cast<int>(obj->getStateRank())); |
| 217 | + parlist->sublist("Reduced Dynamic Objective").set("Adjoint Rank", static_cast<int>(obj->getAdjointRank())); |
| 218 | + parlist->sublist("Reduced Dynamic Objective").set("State Sensitivity Rank", static_cast<int>(obj->getStateSensitivityRank())); |
| 219 | + |
| 220 | + zdiff->set(*z); zdiff->axpy(static_cast<RealT>(-1),*zprev); |
| 221 | + zerr = zdiff->norm(); |
| 222 | + *outStream << std::endl << "Control Difference: " |
| 223 | + << zerr << std::endl << std::endl; |
| 224 | + if (zerr < ztol && algo->getState()->gnorm < static_cast<RealT>(1e-8)) break; |
| 225 | + |
| 226 | + myCost *= static_cast<RealT>(2e0); |
| 227 | + gtol *= static_cast<RealT>(1e-1); gtol = std::max(gtol,static_cast<RealT>(1e-10)); |
| 228 | + wts = {stateCost, myCost}; |
| 229 | + obj_k = ROL::makePtr<PDE_Objective<RealT>>(qoi_vec,wts,dyn_con->getAssembler()); |
| 230 | + dyn_obj = ROL::makePtr<LTI_Objective<RealT>>(*parlist,obj_k,false); |
| 231 | + obj = ROL::makePtr<ROL::ReducedDynamicObjective<RealT>>(dyn_obj, dyn_con, u0, zk, ck, timeStamp, rpl, outStream); |
| 232 | + } |
| 233 | + |
| 234 | + /*************************************************************************/ |
| 235 | + /***************** OUTPUT RESULTS ****************************************/ |
| 236 | + /*************************************************************************/ |
| 237 | + std::clock_t timer_print = std::clock(); |
| 238 | + // Output control to file |
| 239 | + if ( myRank == 0 ) { |
| 240 | + ROL::Ptr<std::vector<RealT>> zn; |
| 241 | + std::ofstream zfile; |
| 242 | + zfile.open("control.txt"); |
| 243 | + zfile << std::scientific << std::setprecision(15); |
| 244 | + for (int n = 0; n < nt; ++n) { |
| 245 | + zn = ROL::dynamicPtrCast<PDE_OptVector<RealT>>(z->get(n))->getParameter()->getVector(); |
| 246 | + for (int i = 0; i < controlDim; ++i) { |
| 247 | + zfile << std::right << std::setw(25) << (*zn)[i]; |
| 248 | + } |
| 249 | + zfile << std::endl; |
| 250 | + } |
| 251 | + zfile.close(); |
| 252 | + } |
| 253 | + // Output state to file |
| 254 | + uo->set(*u0); un->zero(); |
| 255 | + for (int k = 1; k < nt; ++k) { |
| 256 | + // Print previous state to file |
| 257 | + std::stringstream ufile; |
| 258 | + ufile << "state." << k-1 << ".txt"; |
| 259 | + dyn_con->outputTpetraVector(uo_ptr, ufile.str()); |
| 260 | + // Advance time stepper |
| 261 | + dyn_con->solve(*ck, *uo, *un, *z->get(k), timeStamp[k]); |
| 262 | + uo->set(*un); |
| 263 | + } |
| 264 | + // Print previous state to file |
| 265 | + std::stringstream ufile; |
| 266 | + ufile << "state." << nt-1 << ".txt"; |
| 267 | + dyn_con->outputTpetraVector(uo_ptr, ufile.str()); |
| 268 | + *outStream << "Output time: " |
| 269 | + << static_cast<RealT>(std::clock()-timer_print)/static_cast<RealT>(CLOCKS_PER_SEC) |
| 270 | + << " seconds." << std::endl << std::endl; |
| 271 | + } |
| 272 | + catch (std::logic_error& err) { |
| 273 | + *outStream << err.what() << "\n"; |
| 274 | + errorFlag = -1000; |
| 275 | + }; // end try |
| 276 | + |
| 277 | + if (errorFlag != 0) |
| 278 | + std::cout << "End Result: TEST FAILED\n"; |
| 279 | + else |
| 280 | + std::cout << "End Result: TEST PASSED\n"; |
| 281 | + |
| 282 | + return 0; |
| 283 | +} |
0 commit comments