/*
    DFT++ is a density functional package developed by the research group
    of Professor Tomas Arias

    Copyright 1996-2003 Sohrab Ismail-Beigi

    This file is part of DFT++.

    DFT++ is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    DFT++ 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
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with DFT++; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    Please see the file CREDITS for a list of authors.

    For academic users, we request that publications using results obtained with
    this software reference

    "New algebraic formulation of density functional calculation," by Sohrab Ismail-Beigi
    and T.A. Arias, Computer Physics Communications 128:1-2, 1-45 (June 2000).

    and, if using the wavelet basis, further reference

    "Multiresolution analysis of electronic structure: semicardinal and wavelet bases,"
    T.A. Arias, Reviews of Modern Physics 71:1, 267-311 (January 1999).

    and 

    "Robust ab initio calculation of condensed matter: transparent convergence through
    semicardinal multiresolution analysis,'' I.P. Daykov, T.A. Arias, and
    Torkel D. Engeness, Physical Review Letters, 90:21, 216402 (May 2003).

    For your convenience, preprints of the above articles may be obtained from
    http://arXiv.org/abs/cond-mat/9909130, 9805262, and 0204411, respectively.
*/

/*---------------------------- System -----------------------------------*
 *                                                                       *
 *  System class: takes care of System paramters (i.e. the computer      *
 *                system) and parallelization information.               *
 *                                                                       *
 *-----------------------------------------------------------------------*/
#ifndef DFT_SYSTEM_H
#define DFT_SYSTEM_H

#include "Output.h"

class System
{
  /**************************************************
   ** This data structure is the only one          **
   ** that needs to know about the system          **
   ** architecture.                                **
   **                                              **
   ** Static data needs to be                      **
   ** initialized at the very beginning of         **
   ** the program.                                 **
   **                                              **
   ** This class plays the role of the             **
   ** caretaker of parallelization setup (e.g. MPI)**
   ** Never should an object of this class         **
   ** be actually created.                         **
   **************************************************/
protected:
  static int N_Procs, My_procID;

  /**********************************************************************
   * scratch space manager                                              *
   **********************************************************************/

  // this pointer points to a list of pointers, which in turn point to the
  // scratch spaces.
  static void **scratch_pointers;
  
  // lock and length arrays for the scratch spaces
  static int *scratch_locks;
  static int *scratch_lengths;
  static int *scratch_sizes;

  // number of scratch spaces, ie length of above arrays
  static int num_scratch;

public:
#ifdef DFT_THREAD
  // Deault stacksize in bytes for the POSIX threads...here the default is 1M
  static const int thread_stacksize = 1048576;
  static int N_threads;
#endif
  // Where all the logging info. goes...
  static Output *global_log;

  // static member function, initializing system 
  // dependent static members
  static void GlobalInit(int* argc, char*** argv);
  static void GlobalFinalize();

  // Get processor information
  static int Get_procID() { return My_procID; }
  static int Get_N_Procs() { return N_Procs; }
  // Indicates which processor(s) has full IO access.
  // For now, assume processor 0 is such a processor.
  static int Get_IOprocID() { return 0; }

  // If we have thread parallelization
#ifdef DFT_THREAD
  static int Get_N_threads() { return N_threads ; }
  static int Get_thread_stacksize() { return thread_stacksize; }
#endif

  static double get_time();  // provide transparent access to system timer

  // flag: 0 means all procs get the same seed
  //       1 means different seeds on different procs (using timer)
  static void seed_with_time(int flag=1);


  /**********************************************************************
   * scratch space manager                                              *
   **********************************************************************/


  // at the beginning of the program, we set up a number of scratch spaces;
  // this function can be called more than once, with different arguments.
  static void setup_scratch(int howmany, int length, int datasize);

  // call this function to request a scratch space pointer.
  static void* gimme_scratch(int length, int datasize);
  // when you are done, you have to release the scratch space
  static void release_scratch(void *);
  
};


// this is a good place to put the die function
void die(const char *last_words, ...);

#endif // DFT_SYSTEM_H
