Skip to content

Commit 8c660aa

Browse files
committed
Added serialization for optimization studies.
1 parent 2eb26d0 commit 8c660aa

4 files changed

Lines changed: 268 additions & 4 deletions

File tree

FEBioStudio/FEBioStudy.cpp

Lines changed: 177 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,13 @@ SOFTWARE.*/
3131
#include <FEBioRun/FEBioRun.h>
3232
#include <FEBio/FEBioExport4.h>
3333

34-
CFEBioStudy::CFEBioStudy(CModelDocument* doc) : m_doc(doc)
34+
CFEBioStudy::CFEBioStudy(CModelDocument* doc, StudyType type) : m_doc(doc), m_type(type)
3535
{
3636

3737
}
3838

3939
COptimizationStudy::COptimizationStudy(CModelDocument* doc)
40-
: CFEBioStudy(doc)
40+
: CFEBioStudy(doc, STUDY_OPTIMIZATION)
4141
{
4242
SetTypeString("Parameter optimization");
4343
}
@@ -89,3 +89,178 @@ bool COptimizationStudy::Run()
8989
}
9090
return true;
9191
}
92+
93+
void COptimizationStudy::Save(OArchive& ar)
94+
{
95+
ar.WriteChunk(DataField::StudyName , GetName());
96+
ar.WriteChunk(DataField::StudyInfo , GetInfo());
97+
ar.WriteChunk(DataField::LogFileName , m_logFileName.toStdString());
98+
ar.WriteChunk(DataField::OptMethod , m_ops.m_method);
99+
ar.WriteChunk(DataField::ObjTol , m_ops.m_obj_tol);
100+
ar.WriteChunk(DataField::FDiffScale , m_ops.m_f_diff_scale);
101+
ar.WriteChunk(DataField::OutputLevel , m_ops.m_outLevel);
102+
ar.WriteChunk(DataField::PrintLevel , m_ops.m_printLevel);
103+
ar.WriteChunk(DataField::Objective , m_ops.m_objective);
104+
105+
// parameters
106+
for (size_t i = 0; i < m_ops.m_params.size(); ++i)
107+
{
108+
ar.BeginChunk(DataField::Param);
109+
ar.WriteChunk(0, m_ops.m_params[i].m_name);
110+
ar.WriteChunk(1, m_ops.m_params[i].m_initVal);
111+
ar.WriteChunk(2, m_ops.m_params[i].m_minVal);
112+
ar.WriteChunk(3, m_ops.m_params[i].m_maxVal);
113+
ar.EndChunk();
114+
}
115+
116+
// data-fit model
117+
ar.WriteChunk(DataField::ObjParam, m_ops.m_objParam);
118+
for (size_t i = 0; i < m_ops.m_data.size(); ++i)
119+
{
120+
ar.BeginChunk(DataField::ObjData);
121+
ar.WriteChunk(0, m_ops.m_data[i].m_time);
122+
ar.WriteChunk(1, m_ops.m_data[i].m_value);
123+
ar.EndChunk();
124+
}
125+
126+
// target model
127+
for (size_t i = 0; i < m_ops.m_trgVar.size(); ++i)
128+
{
129+
ar.BeginChunk(DataField::TrgVar);
130+
ar.WriteChunk(0, m_ops.m_trgVar[i].m_name);
131+
ar.WriteChunk(1, m_ops.m_trgVar[i].m_val);
132+
ar.EndChunk();
133+
}
134+
135+
// element-data model
136+
ar.WriteChunk(DataField::EDVar, m_ops.m_edVar);
137+
for (size_t i = 0; i < m_ops.m_edData.size(); ++i)
138+
{
139+
ar.BeginChunk(DataField::EDData);
140+
ar.WriteChunk(0, m_ops.m_edData[i].m_id);
141+
ar.WriteChunk(1, m_ops.m_edData[i].m_value);
142+
ar.EndChunk();
143+
}
144+
145+
// node-data model
146+
ar.WriteChunk(DataField::NDVar, m_ops.m_ndVar);
147+
for (size_t i = 0; i < m_ops.m_ndData.size(); ++i)
148+
{
149+
ar.BeginChunk(DataField::NDData);
150+
ar.WriteChunk(0, m_ops.m_ndData[i].m_id);
151+
ar.WriteChunk(1, m_ops.m_ndData[i].m_value);
152+
ar.EndChunk();
153+
}
154+
}
155+
156+
void COptimizationStudy::Load(IArchive& ar)
157+
{
158+
std::string s;
159+
while (ar.OpenChunk() == IArchive::IO_OK)
160+
{
161+
int nid = ar.GetChunkID();
162+
switch (nid)
163+
{
164+
case DataField::StudyName: ar.read(s); SetName(s); break;
165+
case DataField::StudyInfo: ar.read(s); SetInfo(s); break;
166+
case DataField::LogFileName: { ar.read(s); m_logFileName = QString::fromStdString(s); break; }
167+
case DataField::OptMethod: ar.read(m_ops.m_method); break;
168+
case DataField::ObjTol: ar.read(m_ops.m_obj_tol); break;
169+
case DataField::FDiffScale: ar.read(m_ops.m_f_diff_scale); break;
170+
case DataField::OutputLevel: ar.read(m_ops.m_outLevel); break;
171+
case DataField::PrintLevel: ar.read(m_ops.m_printLevel); break;
172+
case DataField::Objective: ar.read(m_ops.m_objective); break;
173+
// parameters
174+
case DataField::Param:
175+
{
176+
FEBioOpt::Param p("");
177+
while (ar.OpenChunk() == IArchive::IO_OK)
178+
{
179+
int nid = ar.GetChunkID();
180+
switch (nid)
181+
{
182+
case 0: ar.read(s); p.m_name = s; break;
183+
case 1: ar.read(p.m_initVal); break;
184+
case 2: ar.read(p.m_minVal); break;
185+
case 3: ar.read(p.m_maxVal); break;
186+
}
187+
ar.CloseChunk();
188+
}
189+
m_ops.AddParameter(p);
190+
break;
191+
}
192+
// data-fit model
193+
case DataField::ObjParam: ar.read(m_ops.m_objParam); break;
194+
case DataField::ObjData:
195+
{
196+
FEBioOpt::Data d;
197+
while (ar.OpenChunk() == IArchive::IO_OK)
198+
{
199+
int nid = ar.GetChunkID();
200+
switch (nid)
201+
{
202+
case 0: ar.read(d.m_time); break;
203+
case 1: ar.read(d.m_value); break;
204+
}
205+
ar.CloseChunk();
206+
}
207+
m_ops.AddData(d.m_time, d.m_value);
208+
break;
209+
}
210+
// target model
211+
case DataField::TrgVar:
212+
{
213+
FEBioOpt::TargetVar v;
214+
while (ar.OpenChunk() == IArchive::IO_OK)
215+
{
216+
int nid = ar.GetChunkID();
217+
switch (nid)
218+
{
219+
case 0: ar.read(s); v.m_name = s; break;
220+
case 1: ar.read(v.m_val); break;
221+
}
222+
ar.CloseChunk();
223+
}
224+
m_ops.m_trgVar.push_back(v);
225+
break;
226+
}
227+
// element-data model
228+
case DataField::EDVar: ar.read(m_ops.m_edVar); break;
229+
case DataField::EDData:
230+
{
231+
FEBioOpt::IDValue v;
232+
while (ar.OpenChunk() == IArchive::IO_OK)
233+
{
234+
int nid = ar.GetChunkID();
235+
switch (nid)
236+
{
237+
case 0: ar.read(v.m_id); break;
238+
case 1: ar.read(v.m_value); break;
239+
}
240+
ar.CloseChunk();
241+
}
242+
m_ops.m_edData.push_back(v);
243+
break;
244+
}
245+
// node-data model
246+
case DataField::NDVar: ar.read(m_ops.m_ndVar); break;
247+
case DataField::NDData:
248+
{
249+
FEBioOpt::IDValue v;
250+
while (ar.OpenChunk() == IArchive::IO_OK)
251+
{
252+
int nid = ar.GetChunkID();
253+
switch (nid)
254+
{
255+
case 0: ar.read(v.m_id); break;
256+
case 1: ar.read(v.m_value); break;
257+
}
258+
ar.CloseChunk();
259+
}
260+
m_ops.m_ndData.push_back(v);
261+
break;
262+
}
263+
}
264+
ar.CloseChunk();
265+
}
266+
}

FEBioStudio/FEBioStudy.h

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,25 +28,55 @@ SOFTWARE.*/
2828
#include "FEBioOpt.h"
2929
#include <QString>
3030

31+
enum StudyType
32+
{
33+
STUDY_INVALID,
34+
STUDY_OPTIMIZATION
35+
};
36+
3137
class CModelDocument;
3238

3339
class CFEBioStudy : public FSThreadedTask
3440
{
3541
public:
36-
CFEBioStudy(CModelDocument* doc);
42+
CFEBioStudy(CModelDocument* doc, StudyType type);
3743

3844
CModelDocument* GetDocument() { return m_doc; }
3945

4046
virtual bool Run() = 0;
4147

4248
virtual QString GetOutputFileName() const { return QString(); }
4349

50+
StudyType GetType() const { return m_type; }
51+
4452
private:
4553
CModelDocument* m_doc;
54+
StudyType m_type;
4655
};
4756

4857
class COptimizationStudy : public CFEBioStudy
4958
{
59+
// Don't change the order of these fields as they are used for serialization!
60+
enum DataField {
61+
StudyName,
62+
StudyInfo,
63+
LogFileName,
64+
OptMethod,
65+
ObjTol,
66+
FDiffScale,
67+
OutputLevel,
68+
PrintLevel,
69+
Objective,
70+
Param,
71+
ObjParam,
72+
ObjData,
73+
TrgVar,
74+
EDVar,
75+
EDData,
76+
NDVar,
77+
NDData
78+
};
79+
5080
public:
5181
COptimizationStudy(CModelDocument* doc);
5282

@@ -57,6 +87,10 @@ class COptimizationStudy : public CFEBioStudy
5787

5888
QString GetOutputFileName() const override { return m_logFileName; }
5989

90+
public:
91+
void Save(OArchive& ar) override;
92+
void Load(IArchive& ar) override;
93+
6094
private:
6195
FEBioOpt m_ops;
6296
QString m_logFileName;

FEBioStudio/ModelDocument.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -524,7 +524,23 @@ void CModelDocument::Save(OArchive& ar)
524524
job->Save(ar);
525525
}
526526
ar.EndChunk();
527-
}
527+
}
528+
529+
// save the study lists
530+
for (int i = 0; i < FEBioStudies(); ++i)
531+
{
532+
CFEBioStudy* study = GetFEBioStudy(i);
533+
ar.BeginChunk(CID_FEBIOSTUDY);
534+
{
535+
ar.WriteChunk(CID_FEBIOSTUDY_TYPE, (int)study->GetType());
536+
ar.BeginChunk(CID_FEBIOSTUDY_DATA);
537+
{
538+
study->Save(ar);
539+
}
540+
ar.EndChunk();
541+
}
542+
ar.EndChunk();
543+
}
528544
}
529545

530546
//-----------------------------------------------------------------------------
@@ -705,6 +721,40 @@ void CModelDocument::Load(IArchive& ar)
705721
m_JobList.Add(job);
706722
job->Load(ar);
707723
}
724+
else if (nid == CID_FEBIOSTUDY)
725+
{
726+
CFEBioStudy* study = nullptr;
727+
while (ar.OpenChunk() == IArchive::IO_OK)
728+
{
729+
int nid = ar.GetChunkID();
730+
if (nid == CID_FEBIOSTUDY_TYPE)
731+
{
732+
int ntype = 0;
733+
ar.read(ntype);
734+
735+
switch (ntype)
736+
{
737+
case StudyType::STUDY_OPTIMIZATION:
738+
study = new COptimizationStudy(this);
739+
break;
740+
default:
741+
assert(false);
742+
ar.log("Unsupported study type found in file. Study will be ignored.");
743+
break;
744+
}
745+
}
746+
else if (nid == CID_FEBIOSTUDY_DATA)
747+
{
748+
if (study)
749+
{
750+
m_StudyList.Add(study);
751+
study->Load(ar);
752+
}
753+
study = nullptr;
754+
}
755+
ar.CloseChunk();
756+
}
757+
}
708758
ar.CloseChunk();
709759
}
710760

FSCore/enum.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,11 @@ SOFTWARE.*/
581581
#define CID_LCONFIG_CUSTOMEFILE 0x000F1010
582582
#define CID_LCONFIG_TEXT 0x000F1011
583583

584+
// --- Studies
585+
#define CID_FEBIOSTUDY 0x000F2000
586+
#define CID_FEBIOSTUDY_TYPE 0x000F2001
587+
#define CID_FEBIOSTUDY_DATA 0x000F2002
588+
584589
// --- Resources
585590
#define CID_RESOURCE_SECTION 0x00100000
586591
#define CID_RESOURCE_IMAGEMODEL 0x00101000

0 commit comments

Comments
 (0)