stagesmanager.h

00001 /*************************************************************************************
00002  * MechSys - A C++ library to simulate (Continuum) Mechanical Systems                *
00003  * Copyright (C) 2005 Dorival de Moraes Pedroso <dorival.pedroso at gmail.com>       *
00004  * Copyright (C) 2005 Raul Dario Durand Farfan  <raul.durand at gmail.com>           *
00005  *                                                                                   *
00006  * This file is part of MechSys.                                                     *
00007  *                                                                                   *
00008  * MechSys is free software; you can redistribute it and/or modify it under the      *
00009  * terms of the GNU General Public License as published by the Free Software         *
00010  * Foundation; either version 2 of the License, or (at your option) any later        *
00011  * version.                                                                          *
00012  *                                                                                   *
00013  * MechSys is distributed in the hope that it will be useful, but WITHOUT ANY        *
00014  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A   *
00015  * PARTICULAR PURPOSE. See the GNU General Public License for more details.          *
00016  *                                                                                   *
00017  * You should have received a copy of the GNU General Public License along with      *
00018  * MechSys; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, *
00019  * Fifth Floor, Boston, MA 02110-1301, USA                                           *
00020  *************************************************************************************/
00021 
00022 #ifndef MECHSYS_FEM_STAGESMANAGER_H
00023 #define MECHSYS_FEM_STAGESMANAGER_H
00024 
00025 #ifdef HAVE_CONFIG_H
00026   #include "config.h"
00027 #else
00028   #ifndef REAL
00029     #define REAL double
00030   #endif
00031 #endif
00032 
00033 #include <algorithm>
00034 
00035 #include "util/string.h"
00036 #include "fem/inputdata.h"
00037 #include "fem/filesdata.h"
00038 #include "fem/data.h"
00039 
00040 namespace FEM
00041 {
00042 
00044 
00052 class StagesManager
00053 {
00054 public:
00055     // Friend prototype for operator <<
00056     friend std::ostream & operator<< (std::ostream & os, FEM::StagesManager const & SM);
00057     // Methods
00058     void Initialize      (InputData * ID, FilesData * FDat, Data * data); // FilesData could be altered in analyis using embedded elements
00059     int  nStages         () const       { return _idat->nSTAGES;      }
00060     int  CurrentStageNum () const       { return _current_stage_num;  }
00061     void ActivateStage   (int iStage);
00062     void DumpStage       (int nStage) {}
00063     void RestoreStage    (int nStage) {}
00064 private:
00065     // Data
00066     int               _current_stage_num;
00067     InputData       * _idat;
00068     FilesData       * _fdat;
00069     Data            * _data;
00070     // Functions
00071     void _alloc_and_fill_nodal_coords();
00072     void _alloc_and_init_elements(); // Allocate elements, initialize connectivities and setup nodal variables (dx,dy,fx,fz, ...)
00073     void _alloc_and_init_embededs();
00074     void _clear_bry_conditions(); 
00075     void _update_nodes_given_face_bry(int iStage); // 1st) Read .face bry information and set Nodes bry values (convert acording to element type)
00076     void _update_nodes_given_node_bry(int iStage); // 2nd) Read .node bry information and set Nodes bry values
00077     void _set_element_attributes(int iStage);
00078 }; // class StagesManager
00079 
00080 
00082 
00083 
00084 inline void StagesManager::Initialize(InputData * ID, FilesData * FDat, Data * data) // {{{
00085 {
00086     _current_stage_num = -1;
00087                  _idat = ID;
00088                  _fdat = FDat;
00089                  _data = data;
00090     _alloc_and_fill_nodal_coords(); // Allocate and fill Nodes inside _data;
00091     _alloc_and_init_elements();     // Allocate elements array with they respective type, ex.: Hex8, Bar2, etc.
00092 } // }}}
00093 
00094 inline void StagesManager::_alloc_and_fill_nodal_coords() // {{{
00095 {
00096     // Allocate _data->Nodes array with information from FilesData _fdat
00097     _data->Nodes.resize(_fdat->Nodes.size());
00098 
00099     // Loop along the number of nodes
00100     for (size_t i=0; i<_data->Nodes.size(); ++i)
00101     {
00102         // Copy coordinates from FilesData _fdat to _data structure
00103         _data->Nodes[i].Initialize(               i,
00104                                   _fdat->Nodes[i].X,
00105                                   _fdat->Nodes[i].Y,
00106                                   _fdat->Nodes[i].Z);
00107     }
00108 } // }}}
00109 
00110 inline void StagesManager::_alloc_and_init_elements() // {{{ 
00111 {
00112     // Allocate _data->Elements array with information from FilesData _fdat
00113     _data->Elements.resize(_fdat->Elements.size());
00114 
00115     // Declare a reference to the first stage structure from FilesData _fdat
00116     FilesData::Stage const & S = _fdat->Stages[0];
00117 
00118     // Loop along the number of elements
00119     for (size_t i=0; i<_data->Elements.size(); ++i)
00120     {
00121         // Declare a reference to the [i] element of _fdat structure
00122         FilesData::Element const & E = _fdat->Elements[i];
00123 
00124         // For [i] element, allocate a new element of type equal to Attribute.EleName, ex.: Hex8, Bar2, etc.
00125         // After this allocation, the array of connectivity will be already set
00126         _data->Elements[i] = AllocElement(S.Attributes[E.IdxAtt].EleName);
00127         _data->Elements[i]->Number = i+1;
00128 
00129         // Initialize connectivities of element [i]
00130         for (size_t j=0; j<E.Connects.size(); ++j)
00131         {
00132             // Copy a pointer of node iNode to the internal connects array
00133             // Remember that inside E.Connects the node numbers start at one (1)
00134             // This method also setup nodal variables (dx,dy, etc.) for node [j] inside element [i] 
00135             _data->Elements[i]->SetNode(static_cast<int>(j), &_data->Nodes[E.Connects[j]-1]);
00136             _data->Nodes[E.Connects[j]-1].Refs()++;
00137         }
00138     }
00139 
00140     // Loop along number of embeddeds elements
00141     if (_fdat->EmbElements.size()>0) _alloc_and_init_embededs();
00142     
00143 } // }}}
00144     
00145 inline void StagesManager::_alloc_and_init_embededs() // {{{
00146 {
00147     // determination of ebedded portions
00148     //
00149     // int iElem, fElem, Elem, nElem, lElem; //initial final actual and next and last element  
00150     FilesData::Stage const & S = _fdat->Stages[0];
00151     int  n_elems = _fdat->Elements.size();
00152     int  n_embs  = _fdat->EmbElements.size();
00153     REAL tiny    = 1E-4;
00154 
00155     for (int i_emb=0; i_emb<n_embs; i_emb++)
00156     {
00157         FilesData::Element & great_embed = _fdat->EmbElements[i_emb];
00158         great_embed.IniVals.resize(1);
00159         great_embed.IniVals[0].resize(1);
00160         great_embed.IniVals[0][0]=0.0;
00161         FilesData::Node & init_node  = _fdat->Nodes[great_embed.Connects[0]-1];
00162         FilesData::Node & final_node = _fdat->Nodes[great_embed.Connects[1]-1];
00163         REAL x1 = init_node.X;
00164         REAL y1 = init_node.Y;
00165         REAL z1 = init_node.Z;
00166         REAL x2 = final_node.X;
00167         REAL y2 = final_node.Y;
00168         REAL z2 = final_node.Z;
00169 
00170         REAL length = sqrt(pow(x2-x1,2)+pow(y2-y1,2)+pow(z2-z1,2));
00171         REAL tinylength=0.01*length;
00172         REAL l = (x2-x1)/length; 
00173         REAL m = (y2-y1)/length; 
00174         REAL n = (z2-z1)/length;
00175         int init_elem   = 0;
00176         int prev_elem   = 0;
00177         int actual_elem = 0;
00178         int next_elem   = 0;
00179         int final_elem  = 0;
00180         //find the initial element
00181         for (int j=0; j<n_elems; j++)
00182             if (_data->Elements[j]->IsInside(x1+tinylength*l, y1+tinylength*m, z1+tinylength*n)) 
00183             {
00184                 init_elem = j; break;
00185             }
00186         //find the final element
00187         for (int j=0; j<n_elems; j++)
00188             if (_data->Elements[j]->IsInside(x2-tinylength*l, y2-tinylength*m, z2-tinylength*n))
00189             {
00190                 final_elem = j; break;
00191             }
00192         REAL xp=x1;
00193         REAL yp=y1;
00194         REAL zp=z1;
00195         REAL x=xp;
00196         REAL y=yp;
00197         REAL z=zp;
00198         actual_elem = prev_elem = init_elem;
00199         next_elem = 0;
00200         REAL step  = length;
00201         bool final = false;
00202 
00203         if (init_elem == final_elem)
00204         {
00205             x=x2; y=y2; z=z2; final=true;
00206         }
00207         
00208         //splitting bar:
00209         do{
00210             if (!final) {
00211                 step *= 0.501;
00212                 x    += step*l;
00213                 y    += step*m;
00214                 z    += step*n;
00215                 for (int j=0; j<n_elems; j++)
00216                     if (_data->Elements[j]->IsInside(x, y, z))
00217                     {
00218                         actual_elem = j; break;
00219                     }
00220             }
00221             if (prev_elem == actual_elem)
00222             {
00223                 REAL bf;
00224                 if (!final)
00225                 { // intersection is reached 
00226                     REAL r, s, t;
00227                     _data->Elements[next_elem]->InverseMap(x,y,z,r,s,t);
00228                     bf = fabs(_data->Elements[next_elem]->BoundDistance(r,s,t));
00229                 }
00230                 if ( final || bf <= tiny )  // intersection is reached
00231                 {
00232                     //Allocate embedded element
00233                     Element  * elem     = AllocElement(S.Attributes[great_embed.IdxAtt].EleName);
00234                     Embedded * embedded = dynamic_cast<Embedded*>(elem);
00235 
00236                     //Set connectivities
00237                     Array<Node*> nodes;
00238                     size_t n_emb_nodes = elem->nNodes();
00239                     nodes.resize(n_emb_nodes);
00240 
00241                     // Initialize connectivities of element 
00242                     size_t n_div = n_emb_nodes - 1;
00243                     for (size_t j=0; j<n_emb_nodes; ++j) 
00244                     {
00245                         nodes[j] = new Node;
00246                         REAL _x = xp + j*(x-xp)/n_div; 
00247                         REAL _y = yp + j*(y-yp)/n_div; 
00248                         REAL _z = zp + j*(z-zp)/n_div; 
00249                         nodes[j]->Initialize(0, _x, _y, _z); 
00250                     }
00251 
00252                     // Initialize references of embedded element (embedded connects and tresspassed element)
00253                     embedded->Initialize(nodes, _data->Elements[actual_elem]);
00254                     
00255                     _data->Elements.push_back(embedded);
00256                     _fdat->Elements.push_back(_fdat->EmbElements[i_emb]);
00257 
00258                     if (final) break; //if this is the final element
00259                     else{ 
00260                         xp=x; yp=y; zp=z;
00261                         if (next_elem==final_elem)
00262                         {
00263                             x=x2; y=y2; z=z2;
00264                             actual_elem = prev_elem = next_elem;
00265                             final = true;
00266                         }
00267                         else
00268                         {
00269                             prev_elem = next_elem;
00270                             step = sqrt(pow(x-x2,2)+pow(y-y2,2)+pow(z-z2,2));
00271                         }
00272                     }
00273                 }else{ //when intersection is forward
00274                     step=fabs(step); //advance
00275                 }
00276             }else{ //when intersection is backward
00277                 step=-fabs(step);//retrocession
00278                 next_elem = actual_elem;
00279             }
00280         }while (true);
00281     }
00282 } // }}}
00283 
00284 inline void StagesManager::_clear_bry_conditions() // {{{
00285 {
00286     for (size_t i=0; i<_data->Nodes.size(); ++i)
00287         _data->Nodes[i].ClearBryValues();
00288 } // }}}
00289 
00290 inline void StagesManager::_update_nodes_given_face_bry(int iStage) // {{{
00291 {
00292     // Declare a reference to the iStage structure inside FilesData _fdat
00293     FilesData::Stage const & S = _fdat->Stages[iStage];
00294 
00295     // Loop along the number of faces
00296     for (size_t i=0; i<_fdat->Faces.size(); ++i)
00297     {
00298         // Index to the FaceBrys array inside a Stage structure.
00299         int idx_bry = _fdat->Faces[i].IdxBry;
00300         if (idx_bry!=-1) // Boundary condition prescribed
00301         {
00302             // Boundary condition structure
00303             FilesData::BryCond const & BC = S.FaceBrys[idx_bry];
00304 
00305             // Number of nodes of face [i]
00306             int n_face_nodes = _fdat->Faces[i].Connects.size(); 
00307 
00308             // Element that contains this face. Remember that inside _fdat OwnerElement numbers start at one (1)
00309             int k_element = _fdat->Faces[i].OwnerElement-1;
00310 
00311             // Declare a const pointer to the [k_element] element of _data structure
00312             FEM::Element * const ptrE = _data->Elements[k_element];
00313 
00314             // Temporary array of pointers to the nodes of the face [i]
00315             Array<FEM::Node*> a_ptr_face_nodes;
00316             a_ptr_face_nodes.resize(n_face_nodes);
00317             for (int j=0; j<n_face_nodes; ++j)
00318             {
00319                 // Remember that inside Connects the node numbers start at one (1)
00320                 int          j_node = _fdat->Faces[i].Connects[j]-1;
00321                 a_ptr_face_nodes[j] = &_data->Nodes[j_node];
00322             }
00323 
00324             // Loop along prescribed boundary keys
00325             for (size_t j=0; j<BC.Names.size(); ++j)
00326             {
00327                 // Check if this key (BC.Names[i]) is essential or not
00328                 if (ptrE->IsEssential(BC.Names[j]))
00329                 {
00330                     // Loop along the nodes of face [i]
00331                     for (int m=0; m<n_face_nodes; ++m)
00332                     {
00333                         // Get a reference to a DOFVarsStruct
00334                         FEM::Node::DOFVarsStruct & dof_var = a_ptr_face_nodes[m]->DOFVar(BC.Names[j]);
00335 
00336                         // Setup Essential nodal variable
00337                         dof_var.EssentialBry = BC.Values[j];
00338                         dof_var.IsEssenPresc = true;
00339                     }
00340                 }
00341                 else
00342                 {
00343                     // Temporary place to put natural boundary name
00344                     String str_dof_name;
00345 
00346                     // Temporary array to put the nodal boundary values
00347                     LinAlg::Vector<REAL> a_nodal_values; // will be resized inside CalcFaceNodalValues() method
00348                     
00349                     // Calculate the nodal values for face [i] according to the type of the correspondent element
00350                     ptrE->CalcFaceNodalValues(BC.Names[j]     ,   // In:  Face DOF Name, ex.: "tx, ty, tz"
00351                                               BC.Values[j]    ,   // In:  Face DOF Value, ex.: 10 kPa, 20 kPa
00352                                               a_ptr_face_nodes,   // In:  Array of ptrs to face nodes
00353                                               str_dof_name    ,   // Out: Nodal DOF Name, ex.: "fx, fy, fz"
00354                                               a_nodal_values  );  // Out: Vector of nodal values
00355 
00356                     // Loop along the nodes of face [i]
00357                     for (int m=0; m<n_face_nodes; ++m)
00358                     {
00359                         // Get a reference to a DOFVarsStruct
00360                         FEM::Node::DOFVarsStruct & dof_var = a_ptr_face_nodes[m]->DOFVar(str_dof_name);
00361 
00362                         // Setup Natural nodal variable
00363                           dof_var.NaturalBry += a_nodal_values(m); // Upgrade (add) existent values
00364                         dof_var.IsEssenPresc  = false;
00365                     }
00366                 }
00367             }
00368         }
00369         // else: Face does not have prescribed boundary condition
00370         //       => default case (ux=?,uy=?,fx=0,fy=0) is already set
00371     }
00372 } // }}}
00373 
00374 inline void StagesManager::_update_nodes_given_node_bry(int iStage) // {{{
00375 {
00376     // Declare a reference to the iStage structure inside FilesData _fdat
00377     FilesData::Stage const & S = _fdat->Stages[iStage];
00378 
00379     // Loop along the number of nodes
00380     for (size_t i=0; i<_fdat->Nodes.size(); ++i)
00381     {
00382         // Index to the NodeBrys array inside a Stage structure.
00383         int idx_bry = _fdat->Nodes[i].IdxBry;
00384         if (idx_bry!=-1 && _data->Nodes[i].Refs()>0) // Boundary condition prescribed
00385         {
00386             // Boundary condition structure
00387             FilesData::BryCond const & BC = S.NodeBrys[idx_bry];
00388 
00389             // Loop along prescribed boundary keys
00390             for (size_t j=0; j<BC.Names.size(); ++j)
00391             {
00392                 // Get a reference to a DOFVarsStruct
00393                 FEM::Node::DOFVarsStruct & dof_var = _data->Nodes[i].DOFVar(BC.Names[j]);
00394                 if (_data->Nodes[i].IsEssential(BC.Names[j]))
00395                 {
00396                     dof_var.EssentialBry = BC.Values[j];
00397                     dof_var.IsEssenPresc = true;
00398                 }
00399                 else
00400                 {
00401                       dof_var.NaturalBry += BC.Values[j]; // Upgrade (add) existent values
00402                     dof_var.IsEssenPresc  = false;
00403                 }
00404             }
00405         }
00406         // else: Nodal does not have prescribed boundary condition
00407         //       => default case (ux=?,uy=?,fx=0,fy=0) is already set
00408     }
00409 } // }}}
00410 
00411 inline void StagesManager::_set_element_attributes(int iStage) // {{{
00412 {
00413     // Declare a reference to the iStage structure inside FilesData _fdat
00414     FilesData::Stage const & S = _fdat->Stages[iStage];
00415 
00416     // Loop along the number of elements
00417     for (size_t i=0; i<_fdat->Elements.size(); ++i)
00418     {
00419         // Index to the Attributes array inside a Stage structure.
00420         int idx_att = _fdat->Elements[i].IdxAtt;
00421 
00422         // Attribute structure
00423         FilesData::Attribute const & A = S.Attributes[idx_att];
00424 
00425         // Set Active/Incactive state
00426         if (A.IsActive) _data->Elements[i]->Activate();
00427         else            _data->Elements[i]->Deactivate();
00428 
00429         // Set properties
00430         _data->Elements[i]->SetProperties(A.Properties);
00431 
00432         // Set Model: for [i] element, allocate a new model of type equal to Attribute.ModelName, ex.: Elastic, SubCam, etc.
00433         _data->Elements[i]->ReAllocateModel(A.ModelName, A.ModelPrms, _fdat->Elements[i].IniVals);
00434     }
00435 } // }}}
00436 
00437 inline void StagesManager::ActivateStage(int iStage) // {{{
00438 {
00439     _current_stage_num = iStage;
00440     _clear_bry_conditions();
00441     _update_nodes_given_face_bry(iStage); // This must be first
00442     _update_nodes_given_node_bry(iStage); // This must be second => will override (increment) face brys
00443     _set_element_attributes(iStage);
00444 
00445 #ifdef DO_DEBUG
00446     std::cout << "Stage " << iStage << " ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
00447     std::cout << (*_data) << std::endl;
00448 #endif
00449     
00450 } // }}}
00451 
00452 }; // namespace FEM
00453 
00454 #endif // MECHSYS_FEM_STAGESMANAGER_H
00455 
00456 // vim:fdm=marker

Generated on Wed Jan 24 15:56:26 2007 for MechSys by  doxygen 1.4.7