SampleWriter.C 5.11 KB
Newer Older
1 2
////////////////////////////////////////////////////////////////////////////////
//
Francois Gygi committed
3 4 5 6
// Copyright (c) 2008 The Regents of the University of California
//
// This file is part of Qbox
//
Francois Gygi committed
7 8
// Qbox is distributed under the terms of the GNU General Public License
// as published by the Free Software Foundation, either version 2 of
Francois Gygi committed
9 10 11 12 13 14
// the License, or (at your option) any later version.
// See the file COPYING in the root directory of this distribution
// or <http://www.gnu.org/licenses/>.
//
////////////////////////////////////////////////////////////////////////////////
//
15 16 17 18 19 20 21 22 23
// SampleWriter.C:
//
////////////////////////////////////////////////////////////////////////////////


#include "SampleWriter.h"
#include "Sample.h"
#include "fstream"
#include "qbox_xmlns.h"
24
#include "Timer.h"
25
#include "SharedFilePtr.h"
26
#include <sstream>
27
#include <iomanip>
28
#include <sys/stat.h>
29
#include <cstring>
30

31 32 33 34 35 36 37
using namespace std;

////////////////////////////////////////////////////////////////////////////////
SampleWriter::SampleWriter(const Context& ctxt) : ctxt_(ctxt) {}

////////////////////////////////////////////////////////////////////////////////
void SampleWriter::writeSample(const Sample& s, const string filename,
Francois Gygi committed
38 39
                              string description, bool base64,
                              bool atomsonly, bool serial, bool save_wfv)
40
{
41 42
  Timer tm;
  tm.start();
43 44 45
  // set default encoding
  string encoding =  base64 ? "base64" : "text";
  const char* filename_cstr = filename.c_str();
46

47
  long long file_size;
48

49
  if ( serial )
50
  {
51 52 53 54
    ofstream os;
    if ( ctxt_.onpe0() )
    {
      os.open(filename_cstr);
55 56
      cout << "  SaveCmd: saving to file " << filename
           << ", encoding=" << encoding << endl;
57

58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
      os <<"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
         <<"<fpmd:sample xmlns:fpmd=\""
         << qbox_xmlns()
         << "\"\n"
         <<" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
         <<" xsi:schemaLocation=\""
         << qbox_xmlns() << " sample.xsd\">"
         << endl;

      os << "<description> " << description
         << " </description>" << endl;
      os << s.atoms;
    }

    if ( !atomsonly )
    {
      s.wf.print(os,encoding,"wavefunction");
Francois Gygi committed
75
      if ( save_wfv && s.wfv != 0 )
76 77 78 79 80 81 82
        s.wfv->print(os,encoding,"wavefunction_velocity");
    }

    if ( ctxt_.onpe0() )
      os << "</fpmd:sample>" << endl;

    os.close();
83
  }
84
  else
85
  {
86
#if USE_MPI
87 88 89
    MPI_File fh;
    MPI_Info info;
    MPI_Info_create(&info);
90

91 92 93 94 95
    int err;
    err = MPI_File_open(ctxt_.comm(),(char*) filename_cstr,
                        MPI_MODE_WRONLY|MPI_MODE_CREATE,info,&fh);
    if ( err != 0 )
      cout << s.ctxt_.mype() << ": error in MPI_File_open: " << err << endl;
96

97
    MPI_File_set_size(fh,0);
98
    ctxt_.barrier();
99 100

    MPI_Status status;
101 102 103 104
#else
    ofstream fh(filename_cstr);
#endif
    SharedFilePtr sfp(ctxt_.comm(),fh);
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
    if ( ctxt_.onpe0() )
    {
      string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
      "<fpmd:sample xmlns:fpmd=\"");
      header += qbox_xmlns();
      header += string("\"\n");
      header += string(
      " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n");
      header += string(" xsi:schemaLocation=\"");
      header += qbox_xmlns();
      header += string(" sample.xsd\">\n");

      string desc = string("<description> ") +
        description +
        string(" </description>\n");

      header += desc;

      ostringstream ss("");
      ss << s.atoms;
      header += ss.str();
126
      int len = header.size();
127
#if USE_MPI
128 129
      err = MPI_File_write_at(sfp.file(),sfp.mpi_offset(),(void*)header.c_str(),
            len,MPI_CHAR,&status);
130
      if ( err != 0 )
131
        cout << ctxt_.mype() << ": error in MPI_File_write: header "
132
             << err << endl;
133
      sfp.advance(len);
134 135 136
#else
      fh.write(header.c_str(),len);
#endif
137
    }
138
    sfp.sync();
139 140 141

    if ( !atomsonly )
    {
142
      s.wf.write(sfp,encoding,"wavefunction");
Francois Gygi committed
143
      if ( save_wfv && s.wfv != 0 )
144
        s.wfv->write(sfp,encoding,"wavefunction_velocity");
145 146
    }

147
    sfp.sync();
148

149 150
    if ( ctxt_.onpe0() )
    {
151
      const char *trailer = "</fpmd:sample>\n";
152
      int len = strlen(trailer);
153
#if USE_MPI
154 155
      err = MPI_File_write_at(sfp.file(),sfp.mpi_offset(),(void*)trailer,
              len,MPI_CHAR,&status);
156
      if ( err != 0 )
157
        cout << ctxt_.mype() << ": error in MPI_File_write: trailer "
158
             << err << endl;
159
      sfp.advance(len);
160 161 162
#else
      fh.write(trailer,len);
#endif
163
    }
164

165
    sfp.sync();
166

167
#if USE_MPI
168
    file_size = sfp.offset();
169 170 171
    err = MPI_File_close(&fh);
    if ( err != 0 )
      cout << ctxt_.mype() << ": error in MPI_File_close: " << err << endl;
172 173
#else
    fh.close();
174 175 176
    struct stat statbuf;
    stat(filename_cstr,&statbuf);
    file_size = statbuf.st_size;
177
#endif
178
  }
179

180 181
  tm.stop();
  if ( ctxt_.onpe0() )
182
  {
183 184
    cout << " SampleWriter: write time: "
         << setprecision(3) << tm.real() << " s"
185
         << endl;
186 187
    if ( !serial )
    {
188
      cout << " SampleWriter: file size: " << file_size << endl;
189
      cout << " SampleWriter: aggregate write rate: "
190 191 192 193
           << setprecision(2) << file_size/(tm.real()*1024*1024)
           << " MB/s" << endl;
    }
  }
194
}