//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // trilinosNoxSolver.cpp - part of the Community Ice Sheet Model (CISM) // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // // Copyright (C) 2005-2014 // CISM contributors - see AUTHORS file for list of contributors // // This file is part of CISM. // // CISM is free software: you can redistribute it and/or modify it // under the terms of the Lesser GNU General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // CISM is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // Lesser GNU General Public License for more details. // // You should have received a copy of the Lesser GNU General Public License // along with CISM. If not, see . // //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Trilinos Objects #include "Piro_Epetra_NOXSolver.hpp" #include "Piro_Epetra_LOCASolver.hpp" #include "trilinosModelEvaluator.hpp" #include "Epetra_MpiComm.h" #include "Teuchos_RCP.hpp" #include "Teuchos_ParameterList.hpp" #include "Teuchos_XMLParameterListHelpers.hpp" #include "Teuchos_StandardCatchMacros.hpp" #include "Teuchos_DefaultMpiComm.hpp" #include "config.inc" using namespace std; using Teuchos::RCP; using Teuchos::rcp; // Objects that are global to the file static RCP Nsolver; static RCP model; static RCP paramList; static RCP Comm_; static EpetraExt::ModelEvaluator::InArgs inArgs; static EpetraExt::ModelEvaluator::OutArgs outArgs; static bool printProc; static int timeStep=1; // time step counter // Use continuation instead of straight Newton for this many time steps: void setCismLocaDefaults(Teuchos::ParameterList& locaList) { Teuchos::ParameterList& predList = locaList.sublist("Predictor"); Teuchos::ParameterList& stepperList = locaList.sublist("Stepper"); Teuchos::ParameterList& stepSizeList = locaList.sublist("Step Size"); // If not set in XML list, set these defaults instead (void) predList.get("Method","Constant"); (void) stepperList.get("Continuation Method","Natural"); (void) stepperList.get("Continuation Parameter","Effstrmin Factor"); (void) stepperList.get("Initial Value",10.0); (void) stepperList.get("Max Steps",10); (void) stepperList.get("Max Value",100.0); // not used (void) stepperList.get("Min Value",0.0); // Important!! (void) stepSizeList.get("Initial Step Size",-3.0); // Important!! (void) stepSizeList.get("Aggressiveness",2.0); // Important!! } extern "C" { void FC_FUNC(noxinit,NOXINIT) ( int* nelems, double* statevector, int* mpi_comm_f, void* blackbox_res) // mpi_comm_f: CISM's fortran mpi communicator { bool succeeded=true; try { // Build the epetra communicator MPI_Comm mpi_comm_c = MPI_Comm_f2c(*mpi_comm_f); Comm_=rcp(new Epetra_MpiComm(mpi_comm_c)); Epetra_Comm& Comm=*Comm_; printProc = (Comm_->MyPID() == 0); Teuchos::MpiComm tcomm(Teuchos::opaqueWrapper(mpi_comm_c)); if (printProc) std::cout << "NOXINIT CALLED for nelem=" << *nelems << std::endl; try { // Check that the parameter list is valid at the top RCP pl = rcp(new Teuchos::ParameterList("Trilinos Options for NOX")); Teuchos::updateParametersFromXmlFileAndBroadcast( "trilinosOptions.xml", pl.ptr(),tcomm); Teuchos::ParameterList validPL("Valid List");; validPL.sublist("Stratimikos"); validPL.sublist("Piro"); pl->validateParameters(validPL, 0); paramList = Teuchos::sublist(pl,"Piro",true); } catch (std::exception& e) { std::cout << "\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n" << e.what() << "\nExiting: Invalid trilinosOptions.xml file." << "\nXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << std::endl; exit(1); } paramList->set("Lean Matrix Free",true); // Saves some GMRES steps //pw if (printProc) std::cout << "NOXInit: param list is: (delete this debug line)\n" << *paramList << std::endl; model = rcp(new trilinosModelEvaluator(*nelems, statevector, Comm, blackbox_res)); // Logic to see if we want to use LOCA continuation or NOX single steady solve // Turn on LOCA by having a LOCA sublist OR setting "CISM: Number of Time Steps To Use LOCA" bool useLoca=false; // If LOCA sublist exists, defaults to using it for 1 time step; but can be set in XML. int numStepsToUseLOCA = 0; if (paramList->isSublist("LOCA")) numStepsToUseLOCA = paramList->get("CISM: Number of Time Steps To Use LOCA",1); else numStepsToUseLOCA = paramList->get("CISM: Number of Time Steps To Use LOCA",0); if (timeStep <= numStepsToUseLOCA) useLoca=true; if (useLoca) if (printProc) std::cout << "\nUsing LOCA continuation for first " << numStepsToUseLOCA << " time steps." << std::endl; if (useLoca) { setCismLocaDefaults(paramList->sublist("LOCA")); Nsolver = rcp(new Piro::Epetra::LOCASolver(paramList, model)); } else Nsolver = rcp(new Piro::Epetra::NOXSolver(paramList, model)); inArgs=Nsolver->createInArgs(); outArgs=Nsolver->createOutArgs(); // Ask the model for the converged solution from g(0) RCP xmap = Nsolver->get_g_map(0); RCP xout = rcp(new Epetra_Vector(*xmap)); outArgs.set_g(0,xout); // Set up parameter vector for continuation runs if (useLoca) { RCP pmap = Nsolver->get_p_map(0); RCP pvec = rcp(new Epetra_Vector(*pmap)); inArgs.set_p(0, pvec); } // Time step counter: just for deciding whether to use continuation on relaxatin param timeStep++; } //end try block TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, succeeded); if (!succeeded) exit(1); } /****************************************************/ void FC_FUNC(noxsolve,NOXSOLVE) (int* nelems, double* statevector, void* blackbox_res) { bool succeeded=true; try { TEUCHOS_TEST_FOR_EXCEPTION(Nsolver==Teuchos::null, logic_error, "Exception: noxsolve called with solver=null: \n" << "You either did not call noxinit first, or called noxfinish already"); if (printProc) std::cout << "NOXSolve called" << std::endl; // Solve Nsolver->evalModel(inArgs,outArgs); // Copy out the solution RCP xout = outArgs.get_g(0); if(xout == Teuchos::null) throw "evalModel is NOT returning a vector"; for (int i=0; i<*nelems; i++) statevector[i] = (*xout)[i]; } TEUCHOS_STANDARD_CATCH_STATEMENTS(true, std::cerr, succeeded); if (!succeeded) exit(1); } /****************************************************/ void FC_FUNC(noxfinish,NOXFINISH) (void) { if (printProc) std::cout << "NOXFinish called" << std::endl; // Free memory Nsolver = Teuchos::null; model = Teuchos::null; paramList = Teuchos::null; Comm_ = Teuchos::null; } } //extern "C"