/[escript]/branches/arrexp_2137_win/escript/src/DataConstant.cpp
ViewVC logotype

Contents of /branches/arrexp_2137_win/escript/src/DataConstant.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2212 - (show annotations)
Wed Jan 14 00:15:00 2009 UTC (10 years, 3 months ago) by jfenwick
File size: 12659 byte(s)
Executive summary:

This commit adds copy on write checks to operations involving shared data. 

Changes:

new #defines:
~~~~~~~~~~~~~
Data.cpp has ASSIGNMENT_MEANS_DEEPCOPY (defaults to undefined).
Defining this will put the data = operator back to making deep copies instead
of sharing data (now the default.)

Data:
~~~~~
. Added exclusiveWrite method to copy the underlying data if it is shared.
. Some operators which took python objects now call the c++ versions intead of duplicating code.

DataAbstract and offspring:
~~~~~~~~~~~~~~~~~~~~~~~~~~~
. Added method to determine whether the data is currently shared.
. Added getVectorRO to children of DataReady.
. Added getTagRO.

. Operations which modify values in place (or return modifiable pointers) now use
a macro to check for sharing. In the case where a modification attempt is detected, it throws an exception. In the future, I will enable this only for debugging.

. This shold not really have been required but the compiler was not choosing the use the const version as I would have liked. Besides, this makes things explict.

. Moved (and de-inlined) getVector in DataConstant (It was virtual in a parent class).

Unit tests:
~~~~~~~~~~~
Added both python and c++ unit tests to check known cases of sharing and "inplace"
modification operations.

General:
~~~~~~~~
Removed some commented out code.

1
2 /*******************************************************
3 *
4 * Copyright (c) 2003-2008 by University of Queensland
5 * Earth Systems Science Computational Center (ESSCC)
6 * http://www.uq.edu.au/esscc
7 *
8 * Primary Business: Queensland, Australia
9 * Licensed under the Open Software License version 3.0
10 * http://www.opensource.org/licenses/osl-3.0.php
11 *
12 *******************************************************/
13
14
15 #include "Data.h"
16 #include "DataConstant.h"
17 #include "DataException.h"
18 #include "esysUtils/EsysAssert.h"
19
20 #include <iostream>
21 #include <boost/python/extract.hpp>
22 #ifdef USE_NETCDF
23 #include <netcdfcpp.h>
24 #endif
25 #ifdef PASO_MPI
26 #include <mpi.h>
27 #endif
28
29 #include <boost/python/extract.hpp>
30 #include "DataMaths.h"
31
32 #define CHECK_FOR_EX_WRITE if (!checkNoSharing()) {throw DataException("Attempt to modify shared object");}
33
34 // #define CHECK_FOR_EX_WRITE if (!checkNoSharing()) {std::ostringstream ss; ss << " Attempt to modify shared object. line " << __LINE__ << " of " << __FILE__; throw DataException(ss.str());}
35
36 using namespace std;
37 using namespace boost::python;
38
39 namespace escript {
40
41 DataConstant::DataConstant(const WrappedArray& value,
42 const FunctionSpace& what)
43 : parent(what,value.getShape())
44 {
45 m_data.copyFromArray(value);
46 }
47
48 DataConstant::DataConstant(const DataConstant& other)
49 : parent(other.getFunctionSpace(),other.getShape())
50 {
51 m_data=other.m_data;
52 }
53
54 DataConstant::DataConstant(const DataConstant& other,
55 const DataTypes::RegionType& region)
56 : parent(other.getFunctionSpace(),DataTypes::getResultSliceShape(region))
57 {
58 //
59 // get the shape of the slice to copy from
60 // DataTypes::ShapeType shape(DataTypes::getResultSliceShape(region));
61 //
62 // allocate space for this new DataConstant's data
63 int len = getNoValues();
64 m_data.resize(len,0.,len);
65 //
66 // create a view of the data with the correct shape
67 // DataArrayView tempView(m_data,shape);
68 DataTypes::RegionLoopRangeType region_loop_range=DataTypes::getSliceRegionLoopRange(region);
69 //
70 // load the view with the data from the slice
71 // tempView.copySlice(other.getPointDataView(),region_loop_range);
72 DataTypes::copySlice(m_data,getShape(),0,other.getVector(),other.getShape(),0,region_loop_range);
73 // setPointDataView(tempView);
74 }
75
76 DataConstant::DataConstant(const FunctionSpace& what,
77 const DataTypes::ShapeType &shape,
78 const DataTypes::ValueType &data)
79 : parent(what,shape)
80 {
81 //
82 // copy the data in the correct format
83 m_data=data;
84 //
85 // create the view of the data
86 // DataArrayView tempView(m_data,shape);
87 // setPointDataView(tempView);
88 }
89
90 string
91 DataConstant::toString() const
92 {
93 return DataTypes::pointToString(m_data,getShape(),0,"");
94 }
95
96
97 DataAbstract*
98 DataConstant::deepCopy()
99 {
100 return new DataConstant(*this);
101 }
102
103
104 DataTypes::ValueType::size_type
105 DataConstant::getPointOffset(int sampleNo,
106 int dataPointNo) const
107 {
108 EsysAssert((validSamplePointNo(dataPointNo) && validSampleNo(sampleNo)),
109 "Invalid index, sampleNo: " << sampleNo << " dataPointNo: " << dataPointNo);
110 //
111 // Whatever the coord's always return the same value as this is constant data.
112 return 0;
113 }
114
115 DataTypes::ValueType::size_type
116 DataConstant::getPointOffset(int sampleNo,
117 int dataPointNo)
118 {
119 EsysAssert((validSamplePointNo(dataPointNo) && validSampleNo(sampleNo)),
120 "Invalid index, sampleNo: " << sampleNo << " dataPointNo: " << dataPointNo);
121 //
122 // Whatever the coord's always return the same value as this is constant data.
123 return 0;
124 }
125
126 DataTypes::ValueType::size_type
127 DataConstant::getLength() const
128 {
129 return m_data.size();
130 }
131
132 // DataArrayView
133 // DataConstant::getDataPoint(int sampleNo,
134 // int dataPointNo)
135 // {
136 // EsysAssert((validSamplePointNo(dataPointNo) && validSampleNo(sampleNo)),
137 // "Invalid index, sampleNo: " << sampleNo << " dataPointNo: " << dataPointNo);
138 // //
139 // // Whatever the coord's always return the same value as this is constant data.
140 // return getPointDataView();
141 // }
142
143 DataAbstract*
144 DataConstant::getSlice(const DataTypes::RegionType& region) const
145 {
146 return new DataConstant(*this,region);
147 }
148
149 void
150 DataConstant::setSlice(const DataAbstract* value,
151 const DataTypes::RegionType& region)
152 {
153 const DataConstant* tempDataConst=dynamic_cast<const DataConstant*>(value);
154 if (tempDataConst==0) {
155 throw DataException("Programming error - casting to DataConstant.");
156 }
157 CHECK_FOR_EX_WRITE
158 //
159 DataTypes::ShapeType shape(DataTypes::getResultSliceShape(region));
160 DataTypes::RegionLoopRangeType region_loop_range=DataTypes::getSliceRegionLoopRange(region);
161 //
162 // check shape:
163 if (getRank()!=region.size()) {
164 throw DataException("Error - Invalid slice region.");
165 }
166 if (getRank()>0 && !DataTypes::checkShape(value->getShape(),shape)) {
167 throw DataException (DataTypes::createShapeErrorMessage(
168 "Error - Couldn't copy slice due to shape mismatch.",shape,value->getShape()));
169 }
170 // getPointDataView().copySliceFrom(tempDataConst->getPointDataView(),region_loop_range);
171 DataTypes::copySliceFrom(m_data,getShape(),0,tempDataConst->getVector(), tempDataConst->getShape(),0,region_loop_range);
172 }
173
174
175
176 void
177 DataConstant::symmetric(DataAbstract* ev)
178 {
179 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
180 if (temp_ev==0) {
181 throw DataException("Error - DataConstant::symmetric: casting to DataConstant failed (propably a programming error).");
182 }
183 /* DataArrayView& thisView=getPointDataView();
184 DataArrayView& evView=ev->getPointDataView();*/
185 DataMaths::symmetric(m_data,getShape(),0,temp_ev->getVector(), temp_ev->getShape(),0);
186 }
187
188 void
189 DataConstant::nonsymmetric(DataAbstract* ev)
190 {
191 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
192 if (temp_ev==0) {
193 throw DataException("Error - DataConstant::nonsymmetric: casting to DataConstant failed (propably a programming error).");
194 }
195 /* DataArrayView& thisView=getPointDataView();
196 DataArrayView& evView=ev->getPointDataView();*/
197 DataMaths::nonsymmetric(m_data,getShape(),0,temp_ev->getVector(), temp_ev->getShape(),0);
198 }
199
200 void
201 DataConstant::trace(DataAbstract* ev, int axis_offset)
202 {
203 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
204 if (temp_ev==0) {
205 throw DataException("Error - DataConstant::trace: casting to DataConstant failed (propably a programming error).");
206 }
207 /* DataArrayView& thisView=getPointDataView();
208 DataArrayView& evView=ev->getPointDataView();*/
209 ValueType& evVec=temp_ev->getVector();
210 const ShapeType& evShape=temp_ev->getShape();
211 DataMaths::trace(m_data,getShape(),0,evVec,evShape,0,axis_offset);
212 }
213
214 void
215 DataConstant::swapaxes(DataAbstract* ev, int axis0, int axis1)
216 {
217 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
218 if (temp_ev==0) {
219 throw DataException("Error - DataConstant::swapaxes: casting to DataConstant failed (propably a programming error).");
220 }
221 // DataArrayView& thisView=getPointDataView();
222 // DataArrayView& evView=ev->getPointDataView();
223 DataMaths::swapaxes(m_data,getShape(),0,temp_ev->getVector(), temp_ev->getShape(),0,axis0,axis1);
224 }
225
226 void
227 DataConstant::transpose(DataAbstract* ev, int axis_offset)
228 {
229 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
230 if (temp_ev==0) {
231 throw DataException("Error - DataConstant::transpose: casting to DataConstant failed (propably a programming error).");
232 }
233 /* DataArrayView& thisView=getPointDataView();
234 DataArrayView& evView=ev->getPointDataView();*/
235 DataMaths::transpose(m_data, getShape(),0, temp_ev->getVector(),temp_ev->getShape(),0,axis_offset);
236 }
237
238 void
239 DataConstant::eigenvalues(DataAbstract* ev)
240 {
241 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
242 if (temp_ev==0) {
243 throw DataException("Error - DataConstant::eigenvalues: casting to DataConstant failed (propably a programming error).");
244 }
245 /* DataArrayView& thisView=getPointDataView();
246 DataArrayView& evView=ev->getPointDataView();*/
247 DataMaths::eigenvalues(m_data,getShape(),0,temp_ev->getVector(), temp_ev->getShape(),0);
248 }
249 void
250 DataConstant::eigenvalues_and_eigenvectors(DataAbstract* ev,DataAbstract* V,const double tol)
251 {
252 DataConstant* temp_ev=dynamic_cast<DataConstant*>(ev);
253 if (temp_ev==0) {
254 throw DataException("Error - DataConstant::eigenvalues_and_eigenvectors: casting to DataConstant failed (propably a programming error).");
255 }
256 DataConstant* temp_V=dynamic_cast<DataConstant*>(V);
257 if (temp_V==0) {
258 throw DataException("Error - DataConstant::eigenvalues_and_eigenvectors: casting to DataConstant failed (propably a programming error).");
259 }
260 // DataArrayView thisView=getPointDataView();
261 // DataArrayView evView=ev->getPointDataView();
262 // DataArrayView VView=V->getPointDataView();
263
264 DataMaths::eigenvalues_and_eigenvectors(m_data, getShape(),0,temp_ev->getVector(), temp_ev->getShape(),0,temp_V->getVector(), temp_V->getShape(),0,tol);
265 }
266
267 void
268 DataConstant::setToZero()
269 {
270 CHECK_FOR_EX_WRITE
271 DataTypes::ValueType::size_type n=m_data.size();
272 for (int i=0; i<n ;++i) m_data[i]=0.;
273 }
274
275 void
276 DataConstant::dump(const std::string fileName) const
277 {
278 #ifdef USE_NETCDF
279 const NcDim* ncdims[DataTypes::maxRank];
280 NcVar* var;
281 int rank = getRank();
282 int type= getFunctionSpace().getTypeCode();
283 int ndims =0;
284 long dims[DataTypes::maxRank];
285 const double* d_ptr=&(m_data[0]);
286 DataTypes::ShapeType shape = getShape();
287 int mpi_iam=getFunctionSpace().getDomain()->getMPIRank();
288 int mpi_num=getFunctionSpace().getDomain()->getMPISize();
289 #ifdef PASO_MPI
290 MPI_Status status;
291 #endif
292
293 #ifdef PASO_MPI
294 /* Serialize NetCDF I/O */
295 if (mpi_iam>0) MPI_Recv(&ndims, 0, MPI_INT, mpi_iam-1, 81802, MPI_COMM_WORLD, &status);
296 #endif
297
298 // netCDF error handler
299 NcError err(NcError::verbose_nonfatal);
300 // Create the file.
301 char *newFileName = Escript_MPI_appendRankToFileName(fileName.c_str(), mpi_num, mpi_iam);
302 NcFile dataFile(newFileName, NcFile::Replace);
303 // check if writing was successful
304 if (!dataFile.is_valid())
305 throw DataException("Error - DataConstant:: opening of netCDF file for output failed.");
306 if (!dataFile.add_att("type_id",0) )
307 throw DataException("Error - DataConstant:: appending data type to netCDF file failed.");
308 if (!dataFile.add_att("rank",rank) )
309 throw DataException("Error - DataConstant:: appending rank attribute to netCDF file failed.");
310 if (!dataFile.add_att("function_space_type",type))
311 throw DataException("Error - DataConstant:: appending function space attribute to netCDF file failed.");
312
313 if (rank == 0) {
314 if( ! (ncdims[0] = dataFile.add_dim("l", 1)) )
315 throw DataException("Error - DataConstant:: appending ncdimension 0 to netCDF file failed.");
316 dims[0]=1,
317 ndims=1;
318 } else {
319 ndims=rank;
320 dims[0]=shape[0];
321 if (! (ncdims[0] = dataFile.add_dim("d0",shape[0])) )
322 throw DataException("Error - DataConstant:: appending ncdimension 0 to netCDF file failed.");
323 if ( rank >1 ) {
324 dims[1]=shape[1];
325 if (! (ncdims[1] = dataFile.add_dim("d1",shape[1])) )
326 throw DataException("Error - DataConstant:: appending ncdimension 1 to netCDF file failed.");
327 }
328 if ( rank >2 ) {
329 dims[2]=shape[2];
330 if (! (ncdims[2] = dataFile.add_dim("d2", shape[2])) )
331 throw DataException("Error - DataConstant:: appending ncdimension 2 to netCDF file failed.");
332 }
333 if ( rank >3 ) {
334 dims[3]=shape[3];
335 if (! (ncdims[3] = dataFile.add_dim("d3", shape[3])) )
336 throw DataException("Error - DataConstant:: appending ncdimension 3 to netCDF file failed.");
337 }
338 }
339
340 if (! ( var = dataFile.add_var("data", ncDouble, ndims, ncdims)) )
341 throw DataException("Error - DataConstant:: appending variable to netCDF file failed.");
342 if (! (var->put(d_ptr,dims)) )
343 throw DataException("Error - DataConstant:: copy data to netCDF buffer failed.");
344 #ifdef PASO_MPI
345 if (mpi_iam<mpi_num-1) MPI_Send(&ndims, 0, MPI_INT, mpi_iam+1, 81802, MPI_COMM_WORLD);
346 #endif
347 #else
348 throw DataException("Error - DataConstant:: dump is not configured with netCDF. Please contact your installation manager.");
349 #endif
350 }
351
352 // These used to be marked as inline in DataConstant.
353 // But they are marked virtual in DataReady
354 DataTypes::ValueType&
355 DataConstant::getVector()
356 {
357 CHECK_FOR_EX_WRITE
358 return m_data;
359 }
360
361 const DataTypes::ValueType&
362 DataConstant::getVector() const
363 {
364 return m_data;
365 }
366
367 const DataTypes::ValueType&
368 DataConstant::getVectorRO() const
369 {
370 return m_data;
371 }
372
373 } // end of namespace

Properties

Name Value
svn:eol-style native
svn:keywords Author Date Id Revision

  ViewVC Help
Powered by ViewVC 1.1.26