![]() |
MechSys
1.0
Computing library for simulations in continuum and discrete mechanics
|
00001 /************************************************************************ 00002 * MechSys - Open Library for Mechanical Systems * 00003 * Copyright (C) 2005 Dorival M. Pedroso, Raúl D. D. Farfan * 00004 * * 00005 * This program is free software: you can redistribute it and/or modify * 00006 * it under the terms of the GNU General Public License as published by * 00007 * the Free Software Foundation, either version 3 of the License, or * 00008 * any later version. * 00009 * * 00010 * This program is distributed in the hope that it will be useful, * 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00013 * GNU General Public License for more details. * 00014 * * 00015 * You should have received a copy of the GNU General Public License * 00016 * along with this program. If not, see <http://www.gnu.org/licenses/> * 00017 ************************************************************************/ 00018 00019 #ifndef MECHSYS_MATFILE_H 00020 #define MECHSYS_MATFILE_H 00021 00022 // Std Lib 00023 #include <sstream> 00024 #include <fstream> 00025 00026 // wxWidgets 00027 #ifdef USE_WXWIDGETS 00028 #include <mechsys/gui/wxdict.h> 00029 #include <mechsys/gui/common.h> 00030 #endif 00031 00032 // MechSys 00033 #include <mechsys/util/maps.h> 00034 #include <mechsys/util/fatal.h> 00035 #include <mechsys/util/util.h> 00036 #define INCLUDE_MODELS_ONLY 00037 #include <mechsys/fem/fem.h> 00038 #undef INCLUDE_MODELS_ONLY 00039 00040 #ifdef USE_WXWIDGETS 00041 class MatFile : public wxWindow 00042 #else 00043 class MatFile 00044 #endif 00045 { 00046 public: 00047 // Constructor 00048 #ifdef USE_WXWIDGETS 00049 MatFile (wxFrame * Parent); 00050 ~MatFile () { Aui.UnInit(); } 00051 #else 00052 MatFile () { ID2Prms = new Dict; ID2Inis = new Dict; } 00053 ~MatFile () { delete ID2Prms; delete ID2Inis; } 00054 #endif 00055 00056 // Methods 00057 void Read (char const * FileName); 00058 void Save (char const * FileName); 00059 00060 #ifdef USE_WXWIDGETS 00061 // Methods 00062 void AddMdl (); 00063 00064 // Data 00065 GUI::WxDictTable * ID2Prms; 00066 GUI::WxDictTable * ID2Inis; 00067 GUI::WxDict * DPrms; 00068 GUI::WxDict * DInis; 00069 wxAuiManager Aui; 00070 wxString LstDir; 00071 wxComboBox * CbxMdl; 00072 String FName; 00073 wxArrayString MNames; 00074 00075 // Events 00076 void OnLoad (wxCommandEvent & Event); 00077 void OnSave (wxCommandEvent & Event); 00078 void OnAdd (wxCommandEvent & Event) { AddMdl (); } 00079 void OnDel (wxCommandEvent & Event); 00080 DECLARE_EVENT_TABLE(); 00081 #else 00082 // Data 00083 Dict * ID2Prms; 00084 Dict * ID2Inis; 00085 #endif 00086 00087 #ifdef USE_BOOST_PYTHON 00088 void PyGetPrmIni (int ID, BPy::dict & Prm, BPy::dict & Ini) 00089 { 00090 ID2Prms->PyGet (ID, Prm); 00091 ID2Inis->PyGet (ID, Ini); 00092 } 00093 #endif 00094 00095 }; 00096 00097 00099 00100 00101 inline void MatFile::Read (char const * FileName) 00102 { 00103 // open material file 00104 std::fstream mat_file(FileName, std::ios::in); 00105 if (!mat_file.is_open()) throw new Fatal("MatFile::Read: Could not open file <%s>",FileName); 00106 00107 // parse 00108 int idxcte = 0; 00109 int idxprm = 0; 00110 int idxini = 0; 00111 int nctes = 0; 00112 int nprms = 0; 00113 int ninis = 0; 00114 int line_num = 1; 00115 bool reading_name = false; 00116 bool reading_ctes = false; 00117 bool reading_prms = false; 00118 bool reading_inis = false; 00119 int ID = 0; 00120 String model_name; 00121 Array<String> const * prm_names = NULL; 00122 Array<String> const * ivs_names = NULL; 00123 ID2Prms->clear (); 00124 ID2Inis->clear (); 00125 while (!mat_file.eof()) 00126 { 00127 String line,key,equal,strval; 00128 std::getline (mat_file,line); 00129 std::istringstream iss(line); 00130 if (iss >> key >> equal >> strval) 00131 { 00132 if (key[0]=='#') { line_num++; continue; } 00133 else if (key=="ID") 00134 { 00135 ID = atoi(strval.CStr()); 00136 if (ID<0) throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: IDs must be greater than zero or equal to zero. %d is invalid",FileName,line_num,ID); 00137 reading_name = true; 00138 } 00139 else if (reading_name) 00140 { 00141 if (key=="name") 00142 { 00143 // iterators to prm and ivs names 00144 Str2ArrayStr_t::const_iterator ita = MODEL_PRM_NAMES.find(strval); 00145 Str2ArrayStr_t::const_iterator itb = MODEL_IVS_NAMES.find(strval); 00146 00147 // check 00148 if (ID2Prms->HasKey(ID)) throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: IDs must be unique. %d is repeated",FileName,line_num,ID); 00149 if (MODEL.find(strval)==MODEL.end()) throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: Model 'name' = %s is not available in MODEL",FileName,line_num,strval.CStr()); 00150 if (ita==MODEL_PRM_NAMES.end()) throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: Model 'name' = %s is not available in MODEL_PRM_NAMES",FileName,line_num,strval.CStr()); 00151 if (itb==MODEL_IVS_NAMES.end()) throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: Model 'name' = %s is not available in MODEL_IVS_NAMES",FileName,line_num,strval.CStr()); 00152 00153 // set 00154 ID2Prms->Set (ID, "name", MODEL(strval)); 00155 model_name = strval; 00156 reading_name = false; 00157 reading_ctes = true; 00158 nctes = 0; 00159 idxcte = -1; 00160 prm_names = &ita->second; 00161 ivs_names = &itb->second; 00162 } 00163 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: 'name' must follow 'ID'. '%s' is invalid or in the wrong place",FileName,line_num,key.CStr()); 00164 } 00165 else if (reading_ctes) 00166 { 00167 if (nctes==0) 00168 { 00169 if (key=="nctes") nctes = atoi(strval.CStr()); 00170 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: 'nctes' must follow 'name'. '%s' is invalid or in the wrong place",FileName,line_num,key.CStr()); 00171 if (nctes==0) 00172 { 00173 reading_ctes = false; 00174 reading_prms = true; 00175 nprms = 0; 00176 idxprm = -1; 00177 } 00178 } 00179 else if (key=="nprms") 00180 { 00181 if (idxcte==nctes-1) 00182 { 00183 reading_ctes = false; 00184 reading_prms = true; 00185 nprms = atoi(strval.CStr()); 00186 idxprm = -1; 00187 } 00188 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: 'nprms' must appear after all 'nctes' constants are read. nctes=%d and %d were read so far",FileName,line_num,nctes,idxcte+1); 00189 } 00190 else if (idxcte<nctes) 00191 { 00192 if (MODEL_CTE_NAMES.Has(key)) 00193 { 00194 ID2Prms->Set (ID, key.CStr(), atof(strval.CStr())); 00195 idxcte++; 00196 } 00197 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: constant named '%s' is not available for model '%s'",FileName,line_num,key.CStr(),model_name.CStr()); 00198 } 00199 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: there are more constants than what specified by nctes=%d. The reading of constants finishes when 'nprms' is found. '%s' is invalid or in the wrong place (idxcte=%d)",FileName,line_num,nctes,key.CStr(),idxcte); 00200 } 00201 else if (reading_prms) 00202 { 00203 if (nprms==0) 00204 { 00205 if (key=="nprms") nprms = atoi(strval.CStr()); 00206 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: 'nprms' must follow constants. '%s' is invalid or in the wrong place",FileName,line_num,key.CStr()); 00207 } 00208 else if (key=="ninis") 00209 { 00210 if (idxprm==nprms-1) 00211 { 00212 ninis = atoi(strval.CStr()); 00213 idxini = -1; 00214 reading_prms = false; 00215 if (ninis>0) reading_inis = true; 00216 else 00217 { 00218 ID2Inis->Set (ID, SDPair()); 00219 reading_inis = false; 00220 } 00221 } 00222 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: 'ninis' must appear after all 'nprms' parameters are read. nprms=%d and %d were read so far",FileName,line_num,nprms,idxprm+1); 00223 } 00224 else if (idxprm<nprms) 00225 { 00226 if (prm_names->Has(key)) 00227 { 00228 ID2Prms->Set (ID, key.CStr(), atof(strval.CStr())); 00229 idxprm++; 00230 } 00231 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: parameter named '%s' is not available for model '%s'",FileName,line_num,key.CStr(),model_name.CStr()); 00232 } 00233 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: there are more parameters than what specified by nprms=%d. The reading of parameters finishes when 'ninis' is found. '%s' is invalid or in the wrong place (idxprm=%d)",FileName,line_num,nprms,key.CStr(),idxprm); 00234 } 00235 else if (reading_inis) 00236 { 00237 if (key=="ID" || key=="name" || key=="nctes" || key=="nprms" || key=="ninis") throw new Fatal("MatFile: Error in <%s> file at line # %d: There are not enough initial values corresponding to ninis=%d. '%s' is the wrong place",FileName,line_num,ninis,key.CStr()); 00238 else if (idxini==ninis-1) 00239 { 00240 reading_name = false; 00241 reading_ctes = false; 00242 reading_prms = false; 00243 reading_inis = false; 00244 } 00245 else if (idxini<ninis) 00246 { 00247 if (ivs_names->Has(key)) 00248 { 00249 ID2Inis->Set (ID, key.CStr(), atof(strval.CStr())); 00250 idxini++; 00251 } 00252 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: initial value '%s' is not available for model '%s'",FileName,line_num,key.CStr(),model_name.CStr()); 00253 } 00254 else throw new Fatal("MatFile::Read: Error in <%s> file at line # %d: there are more initial values than what specified by ninis=%d. The reading of initial values finishes when %d values are read. '%s' is invalid or in the wrong place (idxini)",FileName,line_num,ninis,ninis,key.CStr(),idxini); 00255 } 00256 else throw new Fatal("MatFile::Read: Problem with <%s> file at line # %d. '%s' is invalid or in the wrong place",FileName,line_num,key.CStr()); 00257 } 00258 line_num++; 00259 } 00260 00261 #ifdef USE_WXWIDGETS 00262 DPrms->ReBuild (); 00263 DInis->ReBuild (); 00264 TransferDataToWindow (); 00265 #endif 00266 } 00267 00268 inline void MatFile::Save (char const * FileName) 00269 { 00270 std::ostringstream oss; 00271 oss << "############ Materials ##############\n\n"; 00272 String buf; 00273 for (size_t i=0; i<ID2Prms->Keys.Size(); ++i) 00274 { 00275 int id = ID2Prms->Keys[i]; 00276 SDPair const & prms = (*ID2Prms)(id); 00277 SDPair const & inis = (*ID2Inis)(id); 00278 String name; 00279 MODEL.Val2Key (prms("name"), name); 00280 buf.Printf("%-8s = %d\n", "ID", id); oss<<buf; 00281 buf.Printf("%-8s = %s\n", "name", name.CStr()); oss<<buf; 00282 buf.Printf("%-8s = %d\n", "nprms", prms.Keys.Size()-1); oss<<buf; 00283 for (size_t j=0; j<prms.Keys.Size(); ++j) 00284 { 00285 if (prms.Keys[j]!="name") 00286 { 00287 buf.Printf("%-8s = %g\n", prms.Keys[j].CStr(), prms(prms.Keys[j])); 00288 oss << buf; 00289 } 00290 } 00291 buf.Printf("%-8s = %d\n", "ninis", inis.Keys.Size()); 00292 oss << buf; 00293 for (size_t j=0; j<inis.Keys.Size(); ++j) 00294 { 00295 buf.Printf("%-8s = %g\n", inis.Keys[j].CStr(), inis(inis.Keys[j])); 00296 oss << buf; 00297 } 00298 oss << std::endl; 00299 } 00300 std::fstream of(FileName, std::ios::out); 00301 of << oss.str(); 00302 of.close(); 00303 } 00304 00305 std::ostream & operator<< (std::ostream & os, MatFile const & MF) 00306 { 00307 os << "ID2Prms =\n"; 00308 os << (*MF.ID2Prms) << std::endl; 00309 os << "ID2Inis =\n"; 00310 os << (*MF.ID2Inis) << std::endl; 00311 return os; 00312 } 00313 00314 #ifdef USE_WXWIDGETS 00315 00316 enum 00317 { 00318 ID_MATFILE_LOAD = wxID_HIGHEST+2000, 00319 ID_MATFILE_SAVE , 00320 ID_MATFILE_ADD , 00321 ID_MATFILE_DEL , 00322 }; 00323 00324 BEGIN_EVENT_TABLE(MatFile, wxWindow) 00325 EVT_BUTTON (ID_MATFILE_LOAD, MatFile::OnLoad) 00326 EVT_BUTTON (ID_MATFILE_SAVE, MatFile::OnSave) 00327 EVT_BUTTON (ID_MATFILE_ADD, MatFile::OnAdd) 00328 EVT_BUTTON (ID_MATFILE_DEL, MatFile::OnDel) 00329 END_EVENT_TABLE() 00330 00331 inline MatFile::MatFile (wxFrame * Parent) 00332 : wxWindow (Parent, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE) 00333 { 00334 // force validation of child controls 00335 SetExtraStyle (wxWS_EX_VALIDATE_RECURSIVELY); 00336 00337 // tell wxAuiManager to manage this window 00338 Aui.SetManagedWindow (this); 00339 00340 // control panel 00341 ADD_WXPANEL (pnl, szt, szr, 1, 5); 00342 ADD_WXBUTTON (pnl, szr, ID_MATFILE_LOAD, c0, "Load"); 00343 ADD_WXBUTTON (pnl, szr, ID_MATFILE_SAVE, c1, "Save"); 00344 ADD_WXCOMBOBOX (pnl, szr, wxID_ANY, CbxMdl, "Select Model"); 00345 ADD_WXBUTTON (pnl, szr, ID_MATFILE_ADD, c2, "Add" ); 00346 ADD_WXBUTTON (pnl, szr, ID_MATFILE_DEL, c3, "Del" ); 00347 CbxMdl->SetMinSize (wxSize(200,12)); 00348 00349 // grids and models 00350 ID2Prms = new GUI::WxDictTable; 00351 ID2Inis = new GUI::WxDictTable; 00352 DPrms = new GUI::WxDict (this, ID2Prms); 00353 DInis = new GUI::WxDict (this, ID2Inis); 00354 for (ModelFactory_t::iterator it=ModelFactory.begin(); it!=ModelFactory.end(); ++it) 00355 { 00356 String const & model_name = it->first; 00357 Str2ArrayStr_t::const_iterator iprm = MODEL_PRM_NAMES.find(model_name); 00358 Str2ArrayStr_t::const_iterator iivs = MODEL_IVS_NAMES.find(model_name); 00359 if (iprm==MODEL_PRM_NAMES.end()) WxError("MatFile::MatFile: __internal_error__ Model named <%s> is not in map: MODEL_PRM_NAMES",model_name.CStr()); 00360 if (iivs==MODEL_IVS_NAMES.end()) WxError("MatFile::MatFile: __internal_error__ Model named <%s> is not in map: MODEL_IVS_NAMES",model_name.CStr()); 00361 MNames.Add (model_name); 00362 } 00363 ID2Prms->Val2Name = &MODEL; 00364 CbxMdl->Set (MNames); 00365 if (MNames.size()>0) CbxMdl->SetValue(MNames[0]); 00366 00367 // commit all changes to wxAuiManager 00368 Aui.AddPane (pnl, wxAuiPaneInfo().Name("cpnl") .Caption("Material file: Control Panel") .Top (). DestroyOnClose(false).CaptionVisible(true).CloseButton(false).MinSize(wxSize(100,50)).Floatable(false)); 00369 Aui.AddPane (DPrms, wxAuiPaneInfo().Name("dprms").Caption("Material file: Model parameters").Centre().Position(1).DestroyOnClose(false).CaptionVisible(true).CloseButton(false)); 00370 Aui.AddPane (DInis, wxAuiPaneInfo().Name("dinis").Caption("Material file: Initial values") .Centre().Position(2).DestroyOnClose(false).CaptionVisible(true).CloseButton(false)); 00371 Aui.Update (); 00372 } 00373 00374 inline void MatFile::OnLoad (wxCommandEvent & Event) 00375 { 00376 wxFileDialog fd(this, "Load material (.mat) file", LstDir, "", "*.mat"); 00377 if (fd.ShowModal()==wxID_OK) 00378 { 00379 LstDir = fd.GetDirectory (); 00380 try { Read (fd.GetPath().ToStdString().c_str()); } 00381 catch (Fatal * e) { WxError(e->Msg().CStr()); } 00382 } 00383 } 00384 00385 inline void MatFile::OnSave (wxCommandEvent & Event) 00386 { 00387 TransferDataFromWindow(); // Synchronise (validate/transfer) data in controls 00388 wxFileDialog fd(this, "Save material (.mat) file", LstDir, "", "*.mat", wxFD_SAVE|wxFD_OVERWRITE_PROMPT); 00389 if (fd.ShowModal()==wxID_OK) Save (fd.GetPath().ToStdString().c_str()); 00390 } 00391 00392 inline void MatFile::AddMdl () 00393 { 00394 String model_name = CbxMdl->GetValue().ToStdString(); 00395 int max_id = -1; 00396 for (size_t i=0; i<ID2Prms->Keys.Size(); ++i) if (ID2Prms->Keys[i]>max_id) max_id = ID2Prms->Keys[i]; 00397 int id = max_id + 1; 00398 Str2ArrayStr_t::const_iterator iprm = MODEL_PRM_NAMES.find(model_name); 00399 Str2ArrayStr_t::const_iterator iivs = MODEL_IVS_NAMES.find(model_name); 00400 ID2Prms->Set (id, "name", MODEL(model_name)); 00401 ID2Prms->SetZero (id, iprm->second); 00402 ID2Inis->SetZero (id, iivs->second); 00403 DPrms->ReBuild (); 00404 DInis->ReBuild (); 00405 } 00406 00407 inline void MatFile::OnDel (wxCommandEvent & Event) 00408 { 00409 wxArrayInt sel = (DPrms->Tab->Transposed ? DPrms->Grd->GetSelectedRows() : DPrms->Grd->GetSelectedCols()); 00410 if (DPrms->Tab->Transposed) DPrms->Tab->DeleteRows (sel); 00411 else DPrms->Tab->DeleteCols (sel); 00412 if (DInis->Tab->Transposed) DInis->Tab->DeleteRows (sel); 00413 else DInis->Tab->DeleteCols (sel); 00414 DPrms->ReBuild (); 00415 DInis->ReBuild (); 00416 } 00417 00418 #endif 00419 00420 #endif // MECHSYS_MATFILE_H