Skip to content

Commit 66955d8

Browse files
committed
flux characterization multithreading mostly working
1 parent 3c2830e commit 66955d8

File tree

7 files changed

+419
-131
lines changed

7 files changed

+419
-131
lines changed

app/fluxsimthread.cpp

Lines changed: 265 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,265 @@
1+
#include "fluxsimthread.h"
2+
3+
4+
ssc_bool_t ssc_fluxthread_handler(ssc_module_t, ssc_handler_t, int action, float f0, float f1, const char *s0, const char *, void *data)
5+
{
6+
7+
if (action == SSC_UPDATE)
8+
{
9+
FluxSimThread* F = static_cast<FluxSimThread*>(data);
10+
11+
//we don't know how many total simulations are being run, so just base the progress on a scale of 0-99
12+
F->UpdateStatus((int)f0, 100);
13+
14+
return !F->IsSimulationCancelled();
15+
}
16+
else if (action == SSC_LOG)
17+
return 1;
18+
else
19+
return 0;
20+
}
21+
22+
23+
void FluxSimThread::Setup(int thread_id, int thread_ct, Project *P, ssc_data_t ssc_data)
24+
{
25+
/*
26+
Assign all of the arguments to local memory
27+
*/
28+
_thread_id = thread_id;
29+
_thread_ct = thread_ct;
30+
_P = P;
31+
_ssc_data = ssc_data;
32+
Finished = false;
33+
CancelFlag = false;
34+
35+
//copy over all of the data in the ssc_data object into a new object to avoid memory conflicts
36+
_ssc_data = ssc_data_create();
37+
38+
const char* vname = ssc_data_first(ssc_data);
39+
while (vname != '\0')
40+
{
41+
switch (ssc_data_query(ssc_data, vname))
42+
{
43+
case SSC_NUMBER:
44+
{
45+
ssc_number_t v;
46+
ssc_data_get_number(ssc_data, vname, &v);
47+
ssc_data_set_number(_ssc_data, vname, v);
48+
break;
49+
}
50+
case SSC_STRING:
51+
ssc_data_set_string(_ssc_data, vname, ssc_data_get_string(ssc_data, vname));
52+
break;
53+
case SSC_ARRAY:
54+
{
55+
int n;
56+
ssc_number_t* vals = ssc_data_get_array(ssc_data, vname, &n);
57+
ssc_data_set_array(_ssc_data, vname, vals, n);
58+
break;
59+
}
60+
case SSC_MATRIX:
61+
{
62+
int n, m;
63+
ssc_number_t* vals = ssc_data_get_matrix(ssc_data, vname, &n, &m);
64+
ssc_data_set_matrix(_ssc_data, vname, vals, n, m);
65+
break;
66+
}
67+
}
68+
vname = ssc_data_next(ssc_data);
69+
}
70+
71+
72+
};
73+
74+
void FluxSimThread::CancelSimulation()
75+
{
76+
CancelLock.lock();
77+
CancelFlag = true;
78+
CancelLock.unlock();
79+
}
80+
81+
bool FluxSimThread::IsSimulationCancelled()
82+
{
83+
bool r;
84+
CancelLock.lock();
85+
r = CancelFlag;
86+
CancelLock.unlock();
87+
return r;
88+
}
89+
90+
bool FluxSimThread::IsFinished()
91+
{
92+
bool f;
93+
FinishedLock.lock();
94+
f = Finished;
95+
FinishedLock.unlock();
96+
return f;
97+
}
98+
99+
bool FluxSimThread::IsFinishedWithErrors()
100+
{
101+
bool f;
102+
FinErrLock.lock();
103+
f = FinishedWithErrors;
104+
FinErrLock.unlock();
105+
return f;
106+
}
107+
108+
void FluxSimThread::UpdateStatus(int nsim_complete, int)
109+
{
110+
StatusLock.lock();
111+
_nsim_complete = nsim_complete;
112+
StatusLock.unlock();
113+
}
114+
115+
void FluxSimThread::GetStatus(int *nsim_complete, int *nsim_total)
116+
{
117+
StatusLock.lock();
118+
*nsim_complete = _nsim_complete;
119+
*nsim_total = 100;
120+
StatusLock.unlock();
121+
}
122+
123+
std::vector<std::string> *FluxSimThread::GetSimMessages()
124+
{
125+
return &_sim_messages;
126+
}
127+
128+
void FluxSimThread::StartThread() //Entry()
129+
{
130+
/*
131+
*/
132+
try {
133+
134+
FinErrLock.lock();
135+
FinishedWithErrors = false;
136+
FinErrLock.unlock();
137+
_sim_messages.clear();
138+
139+
140+
//Simulate for each time
141+
{
142+
StatusLock.lock();
143+
bool is_cancel = this->CancelFlag; //check for cancelled simulation
144+
StatusLock.unlock();
145+
if (is_cancel) {
146+
FinishedLock.lock();
147+
Finished = true;
148+
FinishedLock.unlock();
149+
return; // (wxThread::ExitCode)-1;
150+
}
151+
}
152+
153+
ssc_module_t mod_solarpilot = ssc_module_create("solarpilot");
154+
155+
ssc_data_set_number(_ssc_data, "thread_id", _thread_id);
156+
ssc_data_set_number(_ssc_data, "thread_ct", _thread_ct);
157+
ssc_data_set_number(_ssc_data, "calc_fluxmaps", 1.);
158+
159+
bool is_cancel;
160+
161+
StatusLock.lock();
162+
is_cancel = this->CancelFlag;
163+
StatusLock.unlock();
164+
165+
166+
// Run simulation
167+
ssc_bool_t resok = ssc_module_exec_with_handler(mod_solarpilot, _ssc_data, ssc_fluxthread_handler, (void*)this);
168+
169+
if(!resok)
170+
{
171+
message_handler("Flux simulation failed");
172+
int ty; float tms;
173+
for (int k = 0; ; k++)
174+
{
175+
const char *msg = ssc_module_log(mod_solarpilot, k, &ty, &tms);
176+
if (!msg)
177+
break;
178+
message_handler(msg);
179+
}
180+
181+
ssc_module_free(mod_solarpilot);
182+
183+
FinErrLock.lock();
184+
FinishedWithErrors = true;
185+
FinErrLock.unlock();
186+
187+
return;
188+
}
189+
190+
//Check for user cancel
191+
StatusLock.lock();
192+
is_cancel = this->CancelFlag;
193+
StatusLock.unlock();
194+
if (is_cancel) {
195+
FinishedLock.lock();
196+
Finished = true;
197+
FinishedLock.unlock();
198+
return;
199+
}
200+
201+
//collect the results
202+
_results.clear();
203+
int nrow, ncol;
204+
ssc_number_t *opteff_table = ssc_data_get_matrix(_ssc_data, "opteff_table", &nrow, &ncol);
205+
206+
int nflux;
207+
ssc_number_t *flux_table = ssc_data_get_matrix(_ssc_data, "flux_table", &nrow, &nflux);
208+
209+
_results.resize(nrow, std::vector<double>(ncol + nflux));
210+
211+
for (size_t i = 0; i < nrow; i++)
212+
{
213+
for (size_t j = 0; j < ncol; j++)
214+
_results[i][j] = opteff_table[i*nrow + j];
215+
for (size_t j = 0; j < nflux; j++)
216+
_results[i][j + ncol] = flux_table[i*nrow + j];
217+
}
218+
219+
ssc_data_free(_ssc_data);
220+
221+
FinishedLock.lock();
222+
Finished = true;
223+
FinishedLock.unlock();
224+
225+
}
226+
catch (std::runtime_error &e)
227+
{
228+
/* Handle exceptions within a thread by adding the exception to a list and returning normally */
229+
StatusLock.lock();
230+
this->CancelFlag = true;
231+
StatusLock.unlock();
232+
233+
FinishedLock.lock();
234+
Finished = true;
235+
FinishedLock.unlock();
236+
237+
FinErrLock.lock();
238+
FinishedWithErrors = true;
239+
FinErrLock.unlock();
240+
241+
_sim_messages.push_back("Thread " + std::to_string(this->_thread_id) + ": " + e.what());
242+
}
243+
catch (...)
244+
{
245+
/* Handle exceptions within a thread by adding the exception to a list and returning normally */
246+
StatusLock.lock();
247+
this->CancelFlag = true;
248+
StatusLock.unlock();
249+
250+
FinishedLock.lock();
251+
Finished = true;
252+
FinishedLock.unlock();
253+
254+
FinErrLock.lock();
255+
FinishedWithErrors = true;
256+
FinErrLock.unlock();
257+
258+
_sim_messages.push_back("Thread " + std::to_string(this->_thread_id) + ": " + "Caught unspecified error in a flux simulation thread. Simulation was not successful.");
259+
}
260+
261+
return;
262+
263+
};
264+
265+

app/fluxsimthread.h

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#ifndef _FLUXSIMTHREAD_
2+
#define _FLUXSIMTHREAD_ 1
3+
4+
5+
#include "project.h"
6+
7+
#include <thread>
8+
#include <mutex>
9+
10+
class FluxSimThread
11+
{
12+
bool
13+
Finished,
14+
CancelFlag,
15+
FinishedWithErrors;
16+
17+
int _thread_id;
18+
int _thread_ct;
19+
int _nsim_complete;
20+
ssc_data_t _ssc_data;
21+
22+
Project *_P;
23+
std::vector<std::string> _sim_messages;
24+
25+
26+
//wxMutex
27+
std::mutex
28+
StatusLock,
29+
CancelLock,
30+
FinishedLock,
31+
FinErrLock;
32+
33+
public:
34+
std::vector< std::vector< double > > _results;
35+
36+
void Setup(int thread_num, int thread_ct, Project *P, ssc_data_t ssc_data);
37+
38+
void CancelSimulation();
39+
40+
bool IsSimulationCancelled();
41+
42+
bool IsFinished();
43+
44+
bool IsFinishedWithErrors();
45+
46+
void UpdateStatus(int ncomp, int ntot);
47+
48+
void GetStatus(int *ncomp, int *ntot);
49+
50+
std::vector<std::string> *GetSimMessages(); //can be called only after simulation is terminated
51+
52+
void StartThread();
53+
54+
};
55+
56+
57+
#endif
58+

0 commit comments

Comments
 (0)