All Classes Namespaces Files Functions Variables Typedefs Enumerator Pages
BackupRestore.hpp
1 /*
2  Copyright 2014 IRIS AS
3 
4  This file is part of the Open Porous Media project (OPM).
5 
6  OPM is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  OPM is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with OPM. If not, see <http://www.gnu.org/licenses/>.
18 */
19 
20 #ifndef OPM_BACKUPRESTORE_HEADER_INCLUDED
21 #define OPM_BACKUPRESTORE_HEADER_INCLUDED
22 
23 #include <iostream>
24 #include <opm/common/data/SimulationDataContainer.hpp>
25 
26 
27 #include <opm/core/simulator/BlackoilState.hpp>
28 #include <opm/autodiff/WellStateFullyImplicitBlackoil.hpp>
29 
30 namespace Opm {
31 
32  namespace {
33  template <class T>
34  void writeValue( std::ostream& stream, const T& value )
35  {
36  stream.write( (const char *) &value, sizeof( T ) );
37  }
38 
39  template <class T>
40  void readValue( std::istream& stream, T& value )
41  {
42  stream.read( (char *) &value, sizeof( T ) );
43  }
44 
45  // write any container that provides a size method and a data method
46  template <class Vector>
47  void writeContainer( std::ostream& stream, const Vector& vector)
48  {
49  typedef typename Vector :: value_type T;
50  unsigned int size = vector.size() * sizeof( T );
51  writeValue( stream, size );
52  if( size > 0 ) {
53  stream.write( (const char *) vector.data(), size );
54  }
55  }
56 
57  // write map where the key is a std::string
58  // and the value is a std::vector or std::array
59  template <class Map>
60  void writeMap( std::ostream& stream, const Map& m)
61  {
62  const unsigned int mapEntries = m.size();
63  writeValue( stream, mapEntries );
64  if( mapEntries > 0 )
65  {
66  const auto& end = m.end();
67  for(auto it = m.begin(); it != end; ++it )
68  {
69  // write key (assume that key is a container)
70  writeContainer( stream, (*it).first );
71  // write value (assume that value is a container)
72  writeContainer( stream, (*it).second );
73  }
74  }
75  }
76 
77  template <class Container>
78  void resizeContainer( Container& container, size_t size )
79  {
80  container.resize( size );
81  }
82 
83  template <class T, size_t n>
84  void resizeContainer( std::array<T, n>& /* a */, size_t size )
85  {
86  static_cast<void>(size);
87  assert( int(size) == int(n) );
88  }
89 
90  template <class Container>
91  void readData(std::istream& stream, Container& container, size_t datasize)
92  {
93  stream.read( reinterpret_cast<char*>( container.data() ), datasize );
94  }
95 
96  //We need to be careful with string, because string.data() returns something that
97  //"A program shall not alter any of the characters in this sequence."
98  template <>
99  void readData<std::string>(std::istream& stream, std::string& string, size_t datasize)
100  {
101  std::vector<char> raw_data(datasize);
102  readData(stream, raw_data, datasize);
103  string = std::string(raw_data.data(), datasize);
104  }
105 
106  template <class Container>
107  void readContainerImpl( std::istream& stream, Container& container, const bool adjustSize )
108  {
109  typedef typename Container :: value_type T;
110  unsigned int dataSize = 0;
111  readValue( stream, dataSize );
112  if( adjustSize && dataSize > 0 ) {
113  resizeContainer( container, dataSize/sizeof(T) );
114  }
115 
116  if( dataSize != container.size() * sizeof( T ) )
117  {
118  OPM_THROW(std::logic_error,
119  "Size of stored data and simulation data does not match "
120  << dataSize << " " << (container.size() * sizeof( T )) );
121  }
122  if( dataSize > 0 ) {
123  readData(stream, container, dataSize);
124  }
125  }
126 
127  template <class Container>
128  void readAndResizeContainer( std::istream& stream, Container& container )
129  {
130  readContainerImpl( stream, container, true );
131  }
132 
133  template <class Container>
134  void readContainer( std::istream& stream, Container& container )
135  {
136  readContainerImpl( stream, container, false );
137  }
138 
139  template <class Map>
140  void readMap( std::istream& stream, Map& m)
141  {
142  m.clear();
143  unsigned int mapEntries = 0;
144  readValue( stream, mapEntries );
145  for( unsigned int entry = 0; entry<mapEntries; ++entry )
146  {
147  std::pair< typename Map :: key_type, typename Map :: mapped_type > mapEntry;
148  // read key
149  readAndResizeContainer( stream, mapEntry.first );
150  // read values
151  readContainer( stream, mapEntry.second );
152 
153  // insert entry into map
154  m.insert( mapEntry );
155  }
156  }
157 
158  enum { SimulatorStateId = 0,
159  WellStateId = 1,
160  WellStateFullyImplicitBackoilId = 3 };
161 
162  inline int objectId( const SimulationDataContainer& /* state */) {
163  return SimulatorStateId;
164  }
165 
166  inline int objectId( const WellState& /* state */) {
167  return WellStateId;
168  }
169 
170  inline int objectId( const WellStateFullyImplicitBlackoil& /* state */) {
171  return WellStateFullyImplicitBackoilId;
172  }
173 
174  template <class State>
175  void checkObjectId( std::istream& in, const State& state )
176  {
177  // read id and compare with object
178  int id = -1;
179  readValue( in, id );
180  if( id != objectId( state ) ) {
181  OPM_THROW(std::logic_error,"backup-restore object type mismatch");
182  }
183  }
184  }
185 
186  // SimulationDataContainer
187  inline
188  std::ostream& operator << (std::ostream& out, const SimulationDataContainer& state )
189  {
190  // write id of object to stream
191  writeValue( out, objectId( state ) );
192 
193  const int numPhases = state.numPhases();
194  writeValue( out, numPhases );
195 
196  // write variables
197  writeContainer( out, state.pressure() );
198  writeContainer( out, state.temperature() );
199  writeContainer( out, state.facepressure() );
200  writeContainer( out, state.faceflux() );
201  writeContainer( out, state.saturation() );
202 
203  return out;
204  }
205 
206  inline
207  std::istream& operator >> (std::istream& in, SimulationDataContainer& state )
208  {
209  // check id of stored object
210  checkObjectId( in, state );
211 
212  int numPhases = 0;
213  readValue( in, numPhases );
214 
215  if( numPhases != (int) state.numPhases() )
216  OPM_THROW(std::logic_error,"num phases wrong");
217 
218  // read variables
219  readContainer( in, state.pressure() );
220  readContainer( in, state.temperature() );
221  readContainer( in, state.facepressure() );
222  readContainer( in, state.faceflux() );
223  readContainer( in, state.saturation() );
224 
225  return in;
226  }
227 
228  // WellState
229  inline
230  std::ostream& operator << (std::ostream& out, const WellState& state )
231  {
232  // write id of object to stream
233  writeValue( out, objectId( state ) );
234 
235  // backup well state
236  writeContainer( out, state.bhp() );
237  writeContainer( out, state.temperature() );
238  writeContainer( out, state.wellRates() );
239  writeContainer( out, state.perfRates() );
240  writeContainer( out, state.perfPress() );
241 
242  return out;
243  }
244 
245  inline
246  std::istream& operator >> (std::istream& in, WellState& state )
247  {
248  // check id of stored object
249  checkObjectId( in, state );
250 
251  // restore well state
252  readAndResizeContainer( in, state.bhp() );
253  readAndResizeContainer( in, state.temperature() );
254  readAndResizeContainer( in, state.wellRates() );
255  readAndResizeContainer( in, state.perfRates() );
256  readAndResizeContainer( in, state.perfPress() );
257 
258  return in;
259  }
260 
261  // WellStateFullyImplicitBlackoil
262  inline
263  std::ostream& operator << (std::ostream& out, const WellStateFullyImplicitBlackoil& state )
264  {
265  // write id of object to stream
266  writeValue( out, objectId( state ) );
267 
268  // backup well state
269  const WellState& wellState = static_cast< const WellState& > (state);
270  out << wellState;
271 
272  const int numWells = state.numWells();
273  writeValue( out, numWells );
274  if( numWells > 0 )
275  {
276  const int numPhases = state.numPhases();
277  writeValue( out, numPhases );
278 
279  // backup additional variables
280  writeContainer( out, state.perfPhaseRates() );
281  writeContainer( out, state.currentControls() );
282  writeMap( out, state.wellMap() );
283  }
284 
285  return out;
286  }
287 
288  inline
289  std::istream& operator >> (std::istream& in, WellStateFullyImplicitBlackoil& state )
290  {
291  // check id of stored object
292  checkObjectId( in, state );
293 
294  // restore well state
295  WellState& wellState = static_cast< WellState& > (state);
296  in >> wellState;
297 
298  int numWells = 0;
299  readValue( in, numWells );
300  if( numWells != state.numWells() )
301  OPM_THROW(std::logic_error,"wrong numWells");
302 
303  if( numWells > 0 )
304  {
305  int numPhases = 0;
306  readValue( in, numPhases );
307  if( numPhases != state.numPhases() )
308  OPM_THROW(std::logic_error,"wrong numPhases");
309 
310  // restore additional variables
311  readAndResizeContainer( in, state.perfPhaseRates() );
312  readAndResizeContainer( in, state.currentControls() );
313  readMap( in, state.wellMap() );
314  }
315 
316  return in;
317  }
318 
319 } // namespace Opm
320 
321 #endif // OPM_BACKUPRESTORE_HEADER_INCLUDED