OpenMD 3.0
Molecular Dynamics in the Open
Loading...
Searching...
No Matches
ifstrstream.cpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2004-present, The University of Notre Dame. All rights
3 * reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * 3. Neither the name of the copyright holder nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 *
31 * SUPPORT OPEN SCIENCE! If you use OpenMD or its source code in your
32 * research, please cite the appropriate papers when you publish your
33 * work. Good starting points are:
34 *
35 * [1] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
36 * [2] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
37 * [3] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
38 * [4] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
39 * [5] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
40 * [6] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
41 * [7] Lamichhane, Newman & Gezelter, J. Chem. Phys. 141, 134110 (2014).
42 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
43 */
44
45/**
46 * @file ifstrstream.cpp
47 * @author Teng Lin
48 * @date 10/14/2004
49 * @version 1.0
50 */
51
52#include "io/ifstrstream.hpp"
53
54#ifdef IS_MPI
55#include <mpi.h>
56#endif
57
58namespace OpenMD {
59
60/** Constructs an object of class ifstream. */
61#ifdef IS_MPI
63 std::basic_istream<char, std::char_traits<char>>(0), internalStringBuf_(),
64 isRead(false) {
65 this->init(&internalStringBuf_);
66 }
67#else
69 std::basic_istream<char, std::char_traits<char>>(0), internalFileBuf_(),
70 isRead(false) {
71 this->init(&internalFileBuf_);
72 }
73#endif
74
75/**
76 * Explicit constructor
77 * \param filename String containing the name of the file to be opened
78 * \param mode Flags describing the requested i/o mode for the file,
79 * default value is ios_base::in
80 * \param checkFilename Flags indicating checking the file name in parallel
81 */
82#ifdef IS_MPI
83 ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode,
84 bool checkFilename) :
85 std::basic_istream<char, std::char_traits<char>>(0),
86 internalStringBuf_(), isRead(false) {
87 this->init(&internalStringBuf_);
88#if defined(_MSC_VER)
89 isRead =
90 internalOpen(filename, mode | std::ios_base::in | std::ios_base::binary,
91 checkFilename);
92#else
93 isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
94#endif
95 }
96#else
97 ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode,
98 bool checkFilename) :
99 std::basic_istream<char, std::char_traits<char>>(0),
100 internalFileBuf_(), isRead(false) {
101 this->init(&internalFileBuf_);
102#if defined(_MSC_VER)
103 isRead =
104 internalOpen(filename, mode | std::ios_base::in | std::ios_base::binary,
105 checkFilename);
106#else
107 isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
108#endif
109 }
110#endif
111 /**
112 * virtual destructor will close the file (in single mode) and clear
113 * the stream buffer
114 */
116
117 /**
118 * Opens a file and associates a buffer with the specified file to
119 * perform the i/o operations (single mode). The primary node reads a
120 * file and broadcasts its content to the secondary nodes. After
121 * broadcasting, all nodes fall back to stringstream (parallel
122 * mode).
123 * \param filename String containing the name of the file to be opened
124 * \param mode Flags describing the requested i/o mode for the file
125 * \param checkFilename Flags indicating checking the file name in parallel
126 */
127 void ifstrstream::open(const char* filename, std::ios_base::openmode mode,
128 bool checkFilename) {
129 if (!isRead) {
130#if defined(_MSC_VER)
131 isRead =
132 internalOpen(filename, mode | std::ios_base::binary, checkFilename);
133#else
134 isRead = internalOpen(filename, mode, checkFilename);
135#endif
136 }
137 }
138
139 /**
140 * Tests if the stream is currently associated with a valid buffer.
141 * \return true if a file has successfully been opened (single mode)
142 * or the whole file has been read and spread among all of the
143 * processors (parallel mode), otherwise false is returned
144 */
146#ifdef IS_MPI
147 return isRead;
148#else
149 // single version fall back to ifstream
150 return internalFileBuf_.is_open();
151#endif
152 }
153
154 /**
155 * In single mode, closes a file. The stream's file buffer is
156 * released from its association with the currently open file. In
157 * parallel mode, cleans up.
158 */
160#ifndef IS_MPI
161 // single version fall back to ifstream
162 if (!internalFileBuf_.close()) this->setstate(std::ios_base::failbit);
163#endif
164
165 isRead = false;
166 }
167
168 /**
169 * Gets the stream buffer object associated with the stream
170 * \return A pointer to the stream buffer object(filebuf in single
171 * mode, stringbuf in parallel mode) associated with the stream.
172 */
173 std::basic_streambuf<char, std::char_traits<char>>* ifstrstream::rdbuf() {
174#ifdef IS_MPI
175 return static_cast<_StringBuf*>(&internalStringBuf_);
176#else
177 return static_cast<_FileBuf*>(&internalFileBuf_);
178#endif
179 }
180
181 /**
182 * Internal function used to open the file
183 * \return true if succesfully opens a file (single mode) or gets
184 * the file content (parallel mode) otherwise return false
185 * \param filename String containing the name of the file to be opened
186 * \param mode Flags describing the requested i/o mode for the file
187 * \param checkFilename Flags indicating checking the file name in parallel
188 * \todo use try - catch syntax to make the program more readable
189 */
190#ifdef IS_MPI
191 bool ifstrstream::internalOpen(const char* filename,
192 std::ios_base::openmode mode,
193 bool checkFilename) {
194 // int commStatus;
195 long fileSize;
196 char* fbuf;
197 int filenameLen;
198 int diffFilename;
199 int error;
200 int myRank;
201 int primaryNode;
202
203 MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
204
205 primaryNode = 0;
206
207 if (myRank == primaryNode) {
208 if (checkFilename) {
209 // check the filename is the same
210 filenameLen = strlen(filename);
211 MPI_Bcast(&filenameLen, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
212 MPI_Bcast((void*)filename, filenameLen, MPI_CHAR, primaryNode,
213 MPI_COMM_WORLD);
214
215 diffFilename = 0;
216 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
217 MPI_COMM_WORLD);
218
219 // if file names are different just return false
220 if (error > 0) return false;
221 }
222
223 std::ifstream fin(filename, mode);
224
225 if (fin.is_open()) {
226 fin.seekg(0, std::ios::end);
227 fileSize = fin.tellg();
228 fin.seekg(0, std::ios::beg);
229
230 // '\0' need one more char
231 fbuf = new char[fileSize + 1];
232
233 assert(fbuf != 0);
234
235 fin.read(fbuf, fileSize);
236
237 if (fin.fail()) fileSize = FileIOError;
238
239 // broadcast the file size
240 MPI_Bcast(&fileSize, 1, MPI_LONG, primaryNode, MPI_COMM_WORLD);
241
242 if (fileSize < 0) {
243 fin.close();
244 delete[] fbuf;
245
246 return false;
247 }
248
249 // make a c-style std::string and broadcast it
250 fbuf[fileSize] = '\0';
251 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, primaryNode, MPI_COMM_WORLD);
252
253 // close the file and delete the buffer
254 fin.close();
255 internalStringBuf_.str(fbuf);
256 delete[] fbuf;
257 } else {
258 fileSize = FileNotExists;
259 MPI_Bcast(&fileSize, 1, MPI_LONG, primaryNode, MPI_COMM_WORLD);
260 return false;
261 }
262
263 } else { // secondary nodes
264
265 // check file name
266 if (checkFilename) {
267 MPI_Bcast(&filenameLen, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
268
269 char* primaryFilename = new char[filenameLen];
270 MPI_Bcast(primaryFilename, filenameLen, MPI_CHAR, primaryNode,
271 MPI_COMM_WORLD);
272
273 if (strcmp(primaryFilename, filename) == 0)
274 diffFilename = 0;
275 else
276 diffFilename = 1;
277
278 delete[] primaryFilename;
279
280 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
281 MPI_COMM_WORLD);
282
283 if (error > 0) return false;
284 }
285 // get file size
286 MPI_Bcast(&fileSize, 1, MPI_LONG, primaryNode, MPI_COMM_WORLD);
287
288 if (fileSize >= 0) {
289 fbuf = new char[fileSize + 1];
290 assert(fbuf);
291
292 // receive file content
293 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, primaryNode, MPI_COMM_WORLD);
294
295 internalStringBuf_.str(fbuf);
296 delete[] fbuf;
297
298 } else if (fileSize == FileNotExists) {
299 return false;
300
301 } else if (fileSize == FileIOError) {
302 return false;
303 }
304 }
305
306 this->clear();
307 return true;
308 }
309#else
310 bool ifstrstream::internalOpen(const char* filename,
311 std::ios_base::openmode mode, bool) {
312 // in single version, fall back to ifstream
313 if (!internalFileBuf_.open(filename, mode)) {
314 this->setstate(std::ios_base::failbit);
315 return false;
316 }
317
318 this->clear();
319 return true;
320 }
321#endif
322} // namespace OpenMD
_Buf * rdbuf()
Gets the stream buffer object associated with the stream.
void open(const char *filename, std::ios_base::openmode mode=std::ios_base::in, bool checkFilename=false)
Opens a file and associates a buffer with the specified file to perform the i/o operations (single mo...
~ifstrstream()
virtual destructor will close the file(in single mode) and clear the stream buffer
bool is_open()
Tests if the stream is currently associated with a valid buffer.
ifstrstream()
Constructs an object of class ifstream.
void close()
In single mode, closes a file.
This basic Periodic Table class was originally taken from the data.cpp file in OpenBabel.