OpenMD 3.2
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 following paper when you publish your work:
33 *
34 * [1] Drisko et al., J. Open Source Softw. 9, 7004 (2024).
35 *
36 * Good starting points for code and simulation methodology are:
37 *
38 * [2] Meineke, et al., J. Comp. Chem. 26, 252-271 (2005).
39 * [3] Fennell & Gezelter, J. Chem. Phys. 124, 234104 (2006).
40 * [4] Sun, Lin & Gezelter, J. Chem. Phys. 128, 234107 (2008).
41 * [5] Vardeman, Stocker & Gezelter, J. Chem. Theory Comput. 7, 834 (2011).
42 * [6] Kuang & Gezelter, Mol. Phys., 110, 691-701 (2012).
43 * [7] Lamichhane, Gezelter & Newman, J. Chem. Phys. 141, 134109 (2014).
44 * [8] Bhattarai, Newman & Gezelter, Phys. Rev. B 99, 094106 (2019).
45 * [9] Drisko & Gezelter, J. Chem. Theory Comput. 20, 4986-4997 (2024).
46 */
47
48/**
49 * @file ifstrstream.cpp
50 * @author Teng Lin
51 * @date 10/14/2004
52 * @version 1.0
53 */
54
55#include "io/ifstrstream.hpp"
56
57#ifdef IS_MPI
58#include <mpi.h>
59#endif
60
61namespace OpenMD {
62
63/** Constructs an object of class ifstream. */
64#ifdef IS_MPI
66 std::basic_istream<char, std::char_traits<char>>(0), internalStringBuf_(),
67 isRead(false) {
68 this->init(&internalStringBuf_);
69 }
70#else
72 std::basic_istream<char, std::char_traits<char>>(0), internalFileBuf_(),
73 isRead(false) {
74 this->init(&internalFileBuf_);
75 }
76#endif
77
78/**
79 * Explicit constructor
80 * \param filename String containing the name of the file to be opened
81 * \param mode Flags describing the requested i/o mode for the file,
82 * default value is ios_base::in
83 * \param checkFilename Flags indicating checking the file name in parallel
84 */
85#ifdef IS_MPI
86 ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode,
87 bool checkFilename) :
88 std::basic_istream<char, std::char_traits<char>>(0),
89 internalStringBuf_(), isRead(false) {
90 this->init(&internalStringBuf_);
91#if defined(_MSC_VER)
92 isRead =
93 internalOpen(filename, mode | std::ios_base::in | std::ios_base::binary,
94 checkFilename);
95#else
96 isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
97#endif
98 }
99#else
100 ifstrstream::ifstrstream(const char* filename, std::ios_base::openmode mode,
101 bool checkFilename) :
102 std::basic_istream<char, std::char_traits<char>>(0),
103 internalFileBuf_(), isRead(false) {
104 this->init(&internalFileBuf_);
105#if defined(_MSC_VER)
106 isRead =
107 internalOpen(filename, mode | std::ios_base::in | std::ios_base::binary,
108 checkFilename);
109#else
110 isRead = internalOpen(filename, mode | std::ios_base::in, checkFilename);
111#endif
112 }
113#endif
114 /**
115 * virtual destructor will close the file (in single mode) and clear
116 * the stream buffer
117 */
119
120 /**
121 * Opens a file and associates a buffer with the specified file to
122 * perform the i/o operations (single mode). The primary node reads a
123 * file and broadcasts its content to the secondary nodes. After
124 * broadcasting, all nodes fall back to stringstream (parallel
125 * mode).
126 * \param filename String containing the name of the file to be opened
127 * \param mode Flags describing the requested i/o mode for the file
128 * \param checkFilename Flags indicating checking the file name in parallel
129 */
130 void ifstrstream::open(const char* filename, std::ios_base::openmode mode,
131 bool checkFilename) {
132 if (!isRead) {
133#if defined(_MSC_VER)
134 isRead =
135 internalOpen(filename, mode | std::ios_base::binary, checkFilename);
136#else
137 isRead = internalOpen(filename, mode, checkFilename);
138#endif
139 }
140 }
141
142 /**
143 * Tests if the stream is currently associated with a valid buffer.
144 * \return true if a file has successfully been opened (single mode)
145 * or the whole file has been read and spread among all of the
146 * processors (parallel mode), otherwise false is returned
147 */
149#ifdef IS_MPI
150 return isRead;
151#else
152 // single version fall back to ifstream
153 return internalFileBuf_.is_open();
154#endif
155 }
156
157 /**
158 * In single mode, closes a file. The stream's file buffer is
159 * released from its association with the currently open file. In
160 * parallel mode, cleans up.
161 */
163#ifndef IS_MPI
164 // single version fall back to ifstream
165 if (!internalFileBuf_.close()) this->setstate(std::ios_base::failbit);
166#endif
167
168 isRead = false;
169 }
170
171 /**
172 * Gets the stream buffer object associated with the stream
173 * \return A pointer to the stream buffer object(filebuf in single
174 * mode, stringbuf in parallel mode) associated with the stream.
175 */
176 std::basic_streambuf<char, std::char_traits<char>>* ifstrstream::rdbuf() {
177#ifdef IS_MPI
178 return static_cast<_StringBuf*>(&internalStringBuf_);
179#else
180 return static_cast<_FileBuf*>(&internalFileBuf_);
181#endif
182 }
183
184 /**
185 * Internal function used to open the file
186 * \return true if succesfully opens a file (single mode) or gets
187 * the file content (parallel mode) otherwise return false
188 * \param filename String containing the name of the file to be opened
189 * \param mode Flags describing the requested i/o mode for the file
190 * \param checkFilename Flags indicating checking the file name in parallel
191 * \todo use try - catch syntax to make the program more readable
192 */
193#ifdef IS_MPI
194 bool ifstrstream::internalOpen(const char* filename,
195 std::ios_base::openmode mode,
196 bool checkFilename) {
197 // int commStatus;
198 long fileSize;
199 char* fbuf;
200 int filenameLen;
201 int diffFilename;
202 int error;
203 int myRank;
204 int primaryNode;
205
206 MPI_Comm_rank(MPI_COMM_WORLD, &myRank);
207
208 primaryNode = 0;
209
210 if (myRank == primaryNode) {
211 if (checkFilename) {
212 // check the filename is the same
213 filenameLen = strlen(filename);
214 MPI_Bcast(&filenameLen, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
215 MPI_Bcast((void*)filename, filenameLen, MPI_CHAR, primaryNode,
216 MPI_COMM_WORLD);
217
218 diffFilename = 0;
219 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
220 MPI_COMM_WORLD);
221
222 // if file names are different just return false
223 if (error > 0) return false;
224 }
225
226 std::ifstream fin(filename, mode);
227
228 if (fin.is_open()) {
229 fin.seekg(0, std::ios::end);
230 fileSize = fin.tellg();
231 fin.seekg(0, std::ios::beg);
232
233 // '\0' need one more char
234 fbuf = new char[fileSize + 1];
235
236 assert(fbuf != 0);
237
238 fin.read(fbuf, fileSize);
239
240 if (fin.fail()) fileSize = FileIOError;
241
242 // broadcast the file size
243 MPI_Bcast(&fileSize, 1, MPI_LONG, primaryNode, MPI_COMM_WORLD);
244
245 if (fileSize < 0) {
246 fin.close();
247 delete[] fbuf;
248
249 return false;
250 }
251
252 // make a c-style std::string and broadcast it
253 fbuf[fileSize] = '\0';
254 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, primaryNode, MPI_COMM_WORLD);
255
256 // close the file and delete the buffer
257 fin.close();
258 internalStringBuf_.str(fbuf);
259 delete[] fbuf;
260 } else {
261 fileSize = FileNotExists;
262 MPI_Bcast(&fileSize, 1, MPI_LONG, primaryNode, MPI_COMM_WORLD);
263 return false;
264 }
265
266 } else { // secondary nodes
267
268 // check file name
269 if (checkFilename) {
270 MPI_Bcast(&filenameLen, 1, MPI_INT, primaryNode, MPI_COMM_WORLD);
271
272 char* primaryFilename = new char[filenameLen];
273 MPI_Bcast(primaryFilename, filenameLen, MPI_CHAR, primaryNode,
274 MPI_COMM_WORLD);
275
276 if (strcmp(primaryFilename, filename) == 0)
277 diffFilename = 0;
278 else
279 diffFilename = 1;
280
281 delete[] primaryFilename;
282
283 MPI_Allreduce(&diffFilename, &error, 1, MPI_INT, MPI_SUM,
284 MPI_COMM_WORLD);
285
286 if (error > 0) return false;
287 }
288 // get file size
289 MPI_Bcast(&fileSize, 1, MPI_LONG, primaryNode, MPI_COMM_WORLD);
290
291 if (fileSize >= 0) {
292 fbuf = new char[fileSize + 1];
293 assert(fbuf);
294
295 // receive file content
296 MPI_Bcast(fbuf, fileSize + 1, MPI_CHAR, primaryNode, MPI_COMM_WORLD);
297
298 internalStringBuf_.str(fbuf);
299 delete[] fbuf;
300
301 } else if (fileSize == FileNotExists) {
302 return false;
303
304 } else if (fileSize == FileIOError) {
305 return false;
306 }
307 }
308
309 this->clear();
310 return true;
311 }
312#else
313 bool ifstrstream::internalOpen(const char* filename,
314 std::ios_base::openmode mode, bool) {
315 // in single version, fall back to ifstream
316 if (!internalFileBuf_.open(filename, mode)) {
317 this->setstate(std::ios_base::failbit);
318 return false;
319 }
320
321 this->clear();
322 return true;
323 }
324#endif
325} // 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.