/[escript]/branches/split/escriptcore/src/SubWorld.cpp
ViewVC logotype

Contents of /branches/split/escriptcore/src/SubWorld.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4808 - (show annotations)
Thu Mar 27 05:34:14 2014 UTC (5 years, 4 months ago) by jfenwick
File size: 7098 byte(s)
More work towards export
1
2 /*****************************************************************************
3 *
4 * Copyright (c) 2014 by University of Queensland
5 * http://www.uq.edu.au
6 *
7 * Primary Business: Queensland, Australia
8 * Licensed under the Open Software License version 3.0
9 * http://www.opensource.org/licenses/osl-3.0.php
10 *
11 * Development until 2012 by Earth Systems Science Computational Center (ESSCC)
12 * Development 2012-2013 by School of Earth Sciences
13 * Development from 2014 by Centre for Geoscience Computing (GeoComp)
14 *
15 *****************************************************************************/
16
17 #include "boost/python/import.hpp"
18 #include "SubWorld.h"
19 #include "SplitWorldException.h"
20
21 #include <iostream>
22
23 using namespace escript;
24 namespace bp=boost::python;
25 using namespace esysUtils;
26
27 SubWorld::SubWorld(JMPI& comm)
28 :mpiinfo(comm), domain((AbstractDomain*)0)
29 {
30
31
32 }
33
34 SubWorld::~SubWorld()
35 {
36 }
37
38 JMPI& SubWorld::getMPI()
39 {
40 return mpiinfo;
41 }
42
43 void SubWorld::setDomain(Domain_ptr d)
44 {
45 domain=d;
46 }
47
48 Domain_ptr SubWorld::getDomain()
49 {
50 return domain;
51 }
52
53 void SubWorld::addJob(boost::python::object j)
54 {
55 jobvec.push_back(j);
56 }
57
58 void SubWorld::clearJobs()
59 {
60 jobvec.clear();
61 }
62
63 // takes an vector of bools of size 2*number of variables
64 // Each entry in the first group is true if this subworld has at least one job which exports that variable.
65 // Each entry in the second group is true if there is at least one Job in this world which wishes
66 // to import that variable.
67 // The order of the variables is determined by the order of keys in the reducemap
68 // Q: Why does it take chars then?
69 // A: Because I want raw storage that I can pass via MPI and bool is special cased.
70 bool SubWorld::localTransport(std::vector<char>& vb, std::string& errmsg)
71 {
72 for (size_t i=0;i<jobvec.size();++i)
73 {
74 bp::dict expmap=bp::extract<bp::dict>(jobvec[i].attr("exportedvalues"))();
75 bp::list items=expmap.items();
76 size_t l=bp::len(items);
77 for (int j=0;j<l;++j)
78 {
79 bp::object o1=items[j][0];
80 bp::object o2=items[j][1];
81 bp::extract<std::string> ex1(o1);
82 if (!ex1.check())
83 {
84 errmsg="Job attempted export using a name which was not a string.";
85 return false;
86 }
87 std::string name=ex1();
88 std::map<std::string, Reducer_ptr>::iterator it=reducemap.find(name);
89 if (it==reducemap.end())
90 {
91 errmsg="Attempt to export variable \""+name+"\". SplitWorld was not told about this variable.";
92 return false;
93 }
94 // so now we know it is a known name, we check that it is not None and that it is compatible
95 if (o2.is_none())
96 {
97 errmsg="Attempt to export variable \""+name+"\" with value of None, this is not permitted.";
98 return false;
99 }
100 if (!(it->second)->valueCompatible(o2))
101 {
102 errmsg="Attempt to export variable \""+name+"\" with an incompatible value.";
103 return false;
104 }
105 if (!(it->second)->reduceLocalValue(o2, errmsg))
106 {
107 return false; // the error string will be set by the reduceLocalValue
108 }
109 }
110 }
111
112 // If we get here, all of the (local) exports worked
113 // Now, lets make a record for distrubtion
114 size_t l=reducemap.size();
115 vb.resize(l*2);
116 size_t i=0;
117 for (str2reduce::iterator it=reducemap.begin();it!=reducemap.end();++it, ++i)
118 {
119 if (it->second->hasValue())
120 {
121 vb[i]=1;
122 }
123 else
124 {
125 vb[i]=0;
126 }
127 if (importmap[it->first])
128 {
129 vb[i+l]=1;
130 }
131 else
132 {
133 vb[i+l]=0;
134 }
135 }
136 return true;
137 }
138 /*
139 // Deal with the i-th job's exports
140 bool SubWorld::processExportsLocal(size_t i, std::string& errmsg)
141 {
142 bp::dict expmap=bp::extract<bp::dict>(jobvec[i].attr("exportedvalues"))();
143 bp::list items=expmap.items();
144 size_t l=bp::len(items);
145 for (int j=0;j<l;++j)
146 {
147 bp::object o1=items[j][0];
148 bp::object o2=items[j][1];
149 bp::extract<std::string> ex1(o1);
150 if (!ex1.check())
151 {
152 errmsg="Job attempted export using a name which was not a string.";
153 return false;
154 }
155 std::string name=ex1();
156 std::map<std::string, Reducer_ptr>::iterator it=reducemap.find(name);
157 if (it==reducemap.end())
158 {
159 errmsg="Attempt to export variable \""+name+"\". SplitWorld was not told about this variable.";
160 return false;
161 }
162 // so now we know it is a known name, we check that it is not None and that it is compatible
163 if (o2.is_none())
164 {
165 errmsg="Attempt to export variable \""+name+"\" with value of None, this is not permitted.";
166 return false;
167 }
168 if (!(it->second)->valueCompatible(o2))
169 {
170 errmsg="Attempt to export variable \""+name+"\" with an incompatible value.";
171 return false;
172 }
173 if (!(it->second)->reduceLocalValue(o2, errmsg))
174 {
175 return false; // the error string will be set by the reduceLocalValue
176 }
177 }
178 return true;
179 }*/
180 /*
181
182 void SubWorld::populateVarMoveInfo(vector<char>& vb)
183 {
184 size_t l=reducemap.size();
185 vb.resize(l*2);
186 for (str2reduce::iterator it=reducemap.begin(), int i=0;it!=reducemap.end();++it, ++i)
187 {
188 if (it->second->hasValue())
189 {
190 vb[i]=1;
191 }
192 else
193 {
194 vb[i]=0;
195 }
196 if (importmap[it->first])
197 {
198 vb[i+l]=1;
199 }
200 else
201 {
202 vb[i+l]=0;
203 }
204 }
205 }*/
206
207 // clears out all the old import and export values from _Jobs_
208 // does not clear values out of reducers
209 void SubWorld::clearImportExports()
210 {
211 for (size_t i=0;i<jobvec.size();++i)
212 {
213 jobvec[i].attr("clearImports")();
214 jobvec[i].attr("clearExports")();
215 }
216 }
217
218 // if 4, a Job performed an invalid export
219 // if 3, a Job threw an exception
220 // if 2, a Job did not return a bool
221 // if 1, at least one Job returned False
222 // if 0, all jobs in this world returned True
223 char SubWorld::runJobs(std::string& errormsg)
224 {
225 errormsg.clear();
226 bp::object gettrace=bp::import("traceback").attr("format_exc");
227 int ret=0;
228 try
229 {
230 for (size_t i=0;i<jobvec.size();++i)
231 {
232 boost::python::object result=jobvec[i].attr("work")();
233 boost::python::extract<bool> ex(result);
234 if (!ex.check() || (result.is_none()))
235 {
236 return 2;
237 }
238 // check to see if we need to keep running
239 if (!ex())
240 {
241 ret=1;
242 }
243
244 }
245 }
246 catch (boost::python::error_already_set e)
247 {
248 using namespace boost::python;
249 PyObject* ptype=0;
250 PyObject* pvalue=0;
251 PyObject* ptraceback=0;
252 PyErr_Fetch(&ptype, &pvalue, &ptraceback);
253 PyErr_NormalizeException(&ptype, &pvalue, &ptraceback);
254
255 PyObject* errobj=PyObject_Str(pvalue);
256
257 errormsg=PyString_AsString(errobj);
258 Py_XDECREF(errobj);
259
260 Py_XDECREF(ptype);
261 Py_XDECREF(pvalue);
262 Py_XDECREF(ptraceback);
263
264 return 3;
265 }
266 return ret;
267 }
268
269 // if manual import is false, add this new variable to all the Jobs in this world
270 void SubWorld::addVariable(std::string& name, Reducer_ptr& rp, bool manualimport)
271 {
272 if (reducemap.find(name)!=reducemap.end())
273 {
274 std::ostringstream oss;
275 oss << "There is already a variable called " << name;
276 throw SplitWorldException(oss.str());
277 }
278 reducemap[name]=rp;
279 if (!manualimport)
280 {
281 for (size_t i=0;i<jobvec.size();++i)
282 {
283 jobvec[i].attr("requestImport")(name);
284 }
285 }
286 }
287
288 void SubWorld::removeVariable(std::string& s)
289 {
290 reducemap.erase(s);
291 }
292

  ViewVC Help
Powered by ViewVC 1.1.26