MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/matfile.h
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines