PISM, A Parallel Ice Sheet Model stable 0.4.1779

src/coupler/ebm_driver.cc

Go to the documentation of this file.
00001 // Copyright (C) 2011 Constantine Khroulev
00002 //
00003 // This file is part of PISM.
00004 //
00005 // PISM is free software; you can redistribute it and/or modify it under the
00006 // terms of the GNU General Public License as published by the Free Software
00007 // Foundation; either version 2 of the License, or (at your option) any later
00008 // version.
00009 //
00010 // PISM is distributed in the hope that it will be useful, but WITHOUT ANY
00011 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00012 // FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
00013 // details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with PISM; if not, write to the Free Software
00017 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00018 
00019 #include "PSExternal.hh"
00020 
00021 // Note: EBM driver code should NOT use any PETSc calls! (The process running
00022 // this code does not initialize PETSc.)
00023 
00024 EBM_driver::EBM_driver(MPI_Comm my_com) {
00025   inter_comm = my_com;
00026   command = "WILL BE INITIALIZED LATER";
00027 }
00028 
00029 int EBM_driver::run() {
00030   int ierr;
00031   int done = 0,
00032     wait_counter = 0,
00033     wait_message_counter = 1;
00034 
00035   // Initialization: get the command.
00036   {
00037     char tmp[PETSC_MAX_PATH_LEN];
00038     MPI_Recv(tmp, PETSC_MAX_PATH_LEN, MPI_CHAR, 0, TAG_EBM_COMMAND, inter_comm, NULL);
00039     command = tmp;
00040   }
00041 
00042   while ( !done ) {
00043     MPI_Status status;
00044     int flag;
00045     MPI_Iprobe(0, MPI_ANY_TAG, inter_comm, &flag, &status);
00046 
00047     if ( !flag ) {
00048       // no message
00049       double sleep_interval = 0.01,
00050         threshold = 3600,
00051         message_interval = 5;  // print a message every 5 seconds
00052       struct timespec rq;
00053       rq.tv_sec = 0;
00054       rq.tv_nsec = (long)(sleep_interval*1e9); // convert to nanoseconds
00055 
00056       if (wait_counter * sleep_interval > threshold) {
00057         fprintf(stderr, "ERROR: spent %1.1f minutes waiting for PISM... Giving up...\n",
00058                 threshold / 60.0);
00059 
00060         done = 1;
00061         continue;
00062       }
00063 
00064       // waiting...
00065       if (sleep_interval * wait_counter / message_interval  > wait_message_counter) { // 
00066         fprintf(stderr, "EBM driver: Waiting for a message from PISM... (%1.1f seconds so far)\n",
00067                 message_interval * wait_message_counter);
00068         wait_message_counter++;
00069       }
00070       nanosleep(&rq, 0);
00071       wait_counter++;
00072       continue;
00073     }
00074 
00075     // we got a message; reset counters
00076     wait_counter = 0;
00077     wait_message_counter = 1;
00078 
00079     switch (status.MPI_TAG) {
00080     case TAG_EBM_RUN:
00081       {
00082         double year;
00083         int ebm_status;
00084         MPI_Recv(&year, 1, MPI_DOUBLE, 0, TAG_EBM_RUN, inter_comm, NULL);
00085         
00086         ierr = run_ebm(year);       // no CHKERRQ(ierr) here
00087 
00088         if (ierr != 0) {
00089           // the run failed
00090           ebm_status = EBM_STATUS_FAILED;
00091           done = 1;
00092         } else {
00093           // we're OK
00094           ebm_status = EBM_STATUS_READY;
00095         }
00096 
00097         MPI_Send(&ebm_status, 1, MPI_INT, 0, TAG_EBM_STATUS, inter_comm);
00098 
00099         break;
00100       }
00101     case TAG_EBM_STOP:
00102       {
00103         int tmp;
00104         MPI_Recv(&tmp, 1, MPI_INT, 0, TAG_EBM_STOP, inter_comm, NULL);
00105         done = 1;
00106         break;
00107       }
00108     default:
00109       {
00110         fprintf(stderr, "ERROR: Unknown message tag: %d\n", status.MPI_TAG);
00111         break;
00112       }
00113     }
00114   } // while (not done)
00115 
00116   return 0;
00117 }
00118 
00119 int EBM_driver::run_ebm(double year) {
00120   int ierr;
00121 
00122   fprintf(stderr, "EBM driver: year = %1.1f. Running '%s'...\n", year, command.c_str());
00123 
00124   ierr = system(command.c_str());
00125 
00126   if (ierr != 0) {
00127     fprintf(stderr, "EBM driver: command exited with the return code %d\n", ierr);
00128     return ierr;
00129   } else {
00130     fprintf(stderr, "EBM driver: command executed succesfully.\n");
00131   }
00132 
00133   return 0; 
00134 }
00135 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines