solver.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_SOLVER_H
00023 #define MECHSYS_FEM_SOLVER_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 "fem/solver/intsolverdata.h"
00034 #include "util/string.h"
00035 #include "fem/data.h"
00036 #include "fem/output.h"
00037 #include "fem/node.h"
00038 #include "fem/ele/element.h"
00039 #include "linalg/vector.h"
00040 #include "linalg/matrix.h"
00041 #include "linalg/lawrap.h"
00042 
00043 namespace FEM
00044 {
00045 
00047 
00052 class Solver
00053 {
00054 public:
00055     // Constructor
00056     Solver(FEM::InputData const & ID, FEM::Data & data, FEM::Output & output);
00057     // Destructor
00058     virtual ~Solver() {}
00059     // Methods
00060     void Solve(int iStage);
00061 protected:
00062     // Data
00063     FEM::InputData            const & _idat;
00064     FEM::Data                       & _data;    // Nodes and elements data
00065     FEM::Output                     & _output;  // Nodes and elements data
00066     Array<FEM::Node::DOFVarsStruct*>  _a_udofs; // Array of ptrs to unknown DOFs.    size = total number of unknown dofs of a current stage
00067     Array<FEM::Node::DOFVarsStruct*>  _a_pdofs; // Array of ptrs to prescribed DOFs. size = total number of prescribed dofs of a current stage
00068     LinAlg::Vector<REAL>              _DF_ext;  // External increment of natural dofs.    size = total number of DOFs
00069     LinAlg::Vector<REAL>              _DU_ext;  // External increment of essential dofs.  size = total number of DOFs
00070 
00071     // Local
00072     void _realloc_and_setup_dof_vectors();
00073     void _assemb_natural_stage_inc();         // Allocate and assemble global (stage) increment of external force vector for the current stage
00074     void _assemb_essential_stage_inc();       // Allocate and assemble global (stage) increment displacements vector for the current stage
00075     void _assemb_K(LinAlg::Matrix<REAL> & K); // Assemble matrix K for the actual state of elements/nodes inside _data
00076 
00077     void _inv_K_times_X(LinAlg::Matrix<REAL> & K           ,  // In/Out: (if DoPreserveK==true => just In)  Out => unknown state (values)
00078                         bool                   DoPreserveK ,  // In:
00079                         LinAlg::Vector<REAL> & X           ,  // In/Out:
00080                         LinAlg::Vector<REAL> & Y           ); // In/Out:   Y <- inv(K)*X   (K*Y=X)
00081     int _n_tot_dof() const { return _a_udofs.size() + _a_pdofs.size(); }
00082 
00083     void _backup_nodes_and_elements_state();
00084     void _update_nodes_and_elements_state(LinAlg::Vector<REAL> const & dU, LinAlg::Vector<REAL> & dF_int);
00085     void _restore_nodes_and_elements_state();
00086 
00087     REAL _norm_essential_vector();
00088     REAL _norm_natural_vector();
00089 
00090     // To be overriden by derived methods
00091     virtual void _do_solve_for_an_increment(int                  const   increment,     // In
00092                                             LinAlg::Vector<REAL> const & dF_ext   ,     // In
00093                                             LinAlg::Vector<REAL> const & dU_ext   ,     // In
00094                                             LinAlg::Matrix<REAL>       & K        ,     // (no needed outside)
00095                                             LinAlg::Vector<REAL>       & dF_int   ,     // (no needed outside)
00096                                             LinAlg::Vector<REAL>       & Rinternal,     // (no needed outside)
00097                                             IntSolverData              & ISD      ) =0; // Out
00098 private:
00099     LinAlg::Vector<REAL> _U_bkp; // A place to store a temporary state of displacements (backup)
00100     LinAlg::Vector<REAL> _F_bkp; // A place to store a temporary state of internal forces (backup)
00101     // Local functions
00102     void _do_scatter(LinAlg::Matrix<REAL> const & K,   // {{{
00103                      LinAlg::Vector<REAL> const & X,
00104                      LinAlg::Vector<REAL> const & Y,
00105                      LinAlg::Matrix<REAL>       & K11, // Unknown_size x Unknown_size
00106                      LinAlg::Matrix<REAL>       & K12, // Unknown_size x Prescribed_size
00107                      LinAlg::Matrix<REAL>       & K21, // Prescribed_size x Unknown_size
00108                      LinAlg::Matrix<REAL>       & K22, // Prescribed_size x Prescribed_size
00109                      LinAlg::Vector<REAL>       & Y2,  // Prescribed_size
00110                      LinAlg::Vector<REAL>       & X1); // Unknown_size }}}
00111 
00112     void _do_gather(LinAlg::Vector<REAL> const & Y1, // Unknown_size {{{
00113                     LinAlg::Vector<REAL> const & Y2, // Prescribed_size
00114                     LinAlg::Vector<REAL> const & X1, // Unknown_size
00115                     LinAlg::Vector<REAL> const & X2, // Prescribed_size
00116                     LinAlg::Vector<REAL>       & Y ,
00117                     LinAlg::Vector<REAL>       & X); // }}}
00118 }; // class Solver
00119 
00120 
00122 
00123 
00124 inline Solver::Solver(FEM::InputData const & ID, FEM::Data & data, FEM::Output & output) // {{{
00125     : _idat   (ID),
00126       _data   (data),
00127       _output (output)
00128 {
00129 } // }}}
00130 
00131 inline void Solver::Solve(int iStage) // {{{
00132 {
00133     // - Realloc DOF vectors: _a_pdofs and _a_pdofs
00134     // - Give an equation ID number to all DOFs inside all nodes
00135     _realloc_and_setup_dof_vectors(); // EqID. OBS.: _n_tot_dof() will work only after this call
00136 
00137     // Allocate auxiliar vectors for backup displacements and internal forces state
00138     _U_bkp.Resize(_n_tot_dof());
00139     _F_bkp.Resize(_n_tot_dof());
00140 
00141     // Allocate and assemble global (stage) increment of external force vector for the current stage
00142     _assemb_natural_stage_inc(); // assemb DF_ext
00143 
00144     // Allocate and assemble global (stage) increment displacements vector for the current stage
00145     _assemb_essential_stage_inc(); // assemb DU_ext
00146 
00147     // ------------------------------------------------------------------------------------ do solve ---
00148 
00149     // Total number of DOF == number of equations
00150     int n_tot_dof = _n_tot_dof();
00151 
00152     // Number of divisions for each increment
00153     int num_div = _idat.nDIV[iStage];
00154 
00155     // Scale increments according to a step controller
00156     REAL lam=1.0/num_div;        // Step controller
00157     LinAlg::Scal(lam, _DF_ext);  // dF_ext <- lam*_DF_ext
00158     LinAlg::Scal(lam, _DU_ext);  // dF_ext <- lam*_DF_ext
00159 
00160     // Allocate K stifness (dense) matrix
00161     LinAlg::Matrix<REAL> K(n_tot_dof, n_tot_dof);
00162 
00163     // Allocate a vector of residual forces = dF_int - dF_ext
00164     LinAlg::Vector<REAL> dF_int   (n_tot_dof);
00165     LinAlg::Vector<REAL> Rinternal(n_tot_dof);
00166 
00167     // Output initial state
00168     if (iStage==0) _output.OutputIncrement(iStage, -1);
00169 
00170     // Loop over increments (0<increment<NumDiv)
00171     for (int increment=0; increment<num_div; ++increment)
00172     {
00173         // Internal solver data
00174         IntSolverData isd;
00175 
00176         // Solve for increment
00177         _do_solve_for_an_increment(increment, _DF_ext, _DU_ext, K, dF_int, Rinternal, isd);
00178 
00179         // Output results for increment
00180         _output.OutputIncrement(iStage, increment, isd);
00181     }
00182 
00183     // Output end of Stage
00184     _output.OutputStage(iStage);
00185     // ----------------------------------------------------------------------------------- end solve ---
00186 } // }}}
00187 
00188 inline void Solver::_realloc_and_setup_dof_vectors() // {{{
00189 {
00190     // ID of equation
00191     int eq_id=0;
00192 
00193     // Deallocate vectors
00194     _a_udofs.resize(0);
00195     _a_pdofs.resize(0);
00196 
00197     // Loop along all nodes
00198     for (size_t i=0; i<_data.Nodes.size(); ++i)
00199     {
00200         // Declare a reference to DOFVars array inside Node [i]
00201         Array<FEM::Node::DOFVarsStruct> & dofs = _data.Nodes[i].DOFVars();
00202 
00203         // Loop along DOFs inside Node [i]
00204         for (size_t j=0; j<dofs.size(); ++j)
00205         {
00206             // Fill DOF vectors
00207             if (dofs[j].IsEssenPresc) _a_pdofs.push_back(&dofs[j]); // prescribed
00208             else                      _a_udofs.push_back(&dofs[j]); // unknown
00209             
00210             // Assing an equation ID to DOF [j]
00211             dofs[j].EqID = eq_id;
00212             eq_id++;
00213         }
00214     }
00215 } // }}}
00216 
00217 inline void Solver::_assemb_natural_stage_inc() // Allocate and assemble global (stage) increment of external force vector for the current stage {{{
00218 {
00219     // Total number of DOF == number of equations
00220     int n_tot_dof = _n_tot_dof();
00221 
00222     // Resize vector DF_ext
00223     _DF_ext.Resize(n_tot_dof);
00224 
00225     // Loop along Unknown_size
00226     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00227         _DF_ext(_a_udofs[iu]->EqID) = _a_udofs[iu]->NaturalBry;
00228 
00229     // Loop along Prescribed_size
00230     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00231         _DF_ext(_a_pdofs[ip]->EqID) = _a_pdofs[ip]->NaturalBry;
00232 } // }}}
00233 
00234 inline void Solver::_assemb_essential_stage_inc() // Allocate and assemble global (stage) increment displacements vector for the current stage {{{
00235 {
00236     // Total number of DOF == number of equations
00237     int n_tot_dof = _n_tot_dof();
00238 
00239     // Resize vector DU_ext
00240     _DU_ext.Resize(n_tot_dof);
00241 
00242     // Loop along Unknown_size
00243     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00244         _DU_ext(_a_udofs[iu]->EqID) = _a_udofs[iu]->EssentialBry;
00245 
00246     // Loop along Prescribed_size
00247     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00248         _DU_ext(_a_pdofs[ip]->EqID) = _a_pdofs[ip]->EssentialBry;
00249 } // }}}
00250 
00251 inline void Solver::_assemb_K(LinAlg::Matrix<REAL> & K) // Assemble matrix K for the actual state of elements/nodes inside _data {{{
00252 {
00253     // Clear K (global) stifness matrix
00254     K.SetValues(0.0);
00255 
00256     // Loop along elements
00257     for (size_t i_ele=0; i_ele<_data.Elements.size(); ++i_ele)
00258     {
00259         // Declare a pointer to Element [i_ele]
00260         FEM::EquilibElem const * const E = dynamic_cast<FEM::EquilibElem *>(_data.Elements[i_ele]);
00261         if (!E) throw new Fatal(_("FEM::Solver: This solver only works for equilibrium type elements"));
00262     
00263         // Allocate an array of position of DOF components inside Ke of Element [i_ele] {{{
00264         /* Ex.:
00265          *               a_map_Ke_to_K_pos[0] = EqID   =>   K[EqID,EqID] = Ke[0,0]
00266          *               a_map_Ke_to_K_pos[1] = EqID   =>   K[EqID,EqID] = Ke[1,1]
00267          *                                      ................
00268          *     a_map_Ke_to_K_pos[Ke.Rows()-1] = EqID   =>   K[EqID,EqID] = Ke[Ke.Rows()-1, Ke.Rows()-1]
00269          *
00270          * Ex.: 
00271          *       Node.NGL=2, Ele.NNODE=2 => Ke.Rows() = 4
00272          *
00273          *             Ke                K(global)_pos
00274          *   _                     _   
00275          *  |  Ke11 Ke12 Ke13 Ke14  | => Ele.Node[0].DOF[0].EqID
00276          *  |  Ke21 Ke22 Ke23 Ke24  | => Ele.Node[0].DOF[1].EqID
00277          *  |  Ke31 Ke32 Ke33 Ke34  | => Ele.Node[1].DOF[0].EqID
00278          *  |_ Ke41 Ke42 Ke43 Ke44 _| => Ele.Node[1].DOF[1].EqID
00279          }}} */
00280             
00281         if (E->IsActive())
00282         {
00283             // Calculate the stiffness matrix of Element [i_ele]
00284             LinAlg::Matrix<REAL> Ke;
00285             Array<size_t> a_map_Ke_to_K_pos; // size=Ke.Rows()=Ke.Cols()
00286             E->Stiffness(Ke, a_map_Ke_to_K_pos);
00287 
00288 
00289             // Assemble local (Ke) DOFs into global (K) matrix
00290             // Loop along Ke (local) matrix Ke.rows and Ke.cols
00291             for (int i_row_Ke=0; i_row_Ke<Ke.Rows(); ++i_row_Ke)
00292             for (int j_col_Ke=0; j_col_Ke<Ke.Rows(); ++j_col_Ke)
00293                 K(a_map_Ke_to_K_pos[i_row_Ke], a_map_Ke_to_K_pos[j_col_Ke]) += Ke(i_row_Ke, j_col_Ke);
00294         }
00295     }
00296 } // }}}
00297 
00298 inline void Solver::_inv_K_times_X(LinAlg::Matrix<REAL> & K           , // In/Out: (if DoPreserveK==true => just In)  Out => unknown state (values) {{{
00299                                    bool                   DoPreserveK , // In:
00300                                    LinAlg::Vector<REAL> & X           , // In/Out:
00301                                    LinAlg::Vector<REAL> & Y           ) // In/Out:
00302 {
00303     // Modify K for essential boundary conditions
00304     //if (_do_split)
00305     //{
00306         /*   _               _  
00307          *  |  [K11] | [K12]  | / {Y1}=? \   / {X1}   \
00308          *  |  - - - - - - -  | | - - -  | = | - - -  |
00309          *  |_ [K21] | [K22] _| \ {Y2}   /   \ {X2}=? /
00310          *
00311          *  {Y2} and {X1} = prescribed
00312          *
00313          *  K11*Y1 + K12*Y2 = X1
00314          *  K21*Y1 + K22*Y2 = X2
00315          *
00316          *  Y1 = inv(K11)*(X1 - K12*Y2)
00317          *  X2 = K21*Y1 + K22*Y2
00318          */
00319 
00320         // Allocate temporary matrices and vectors
00321         LinAlg::Matrix<REAL> K11,K12;
00322         LinAlg::Matrix<REAL> K21,K22;
00323         LinAlg::Vector<REAL> Y2;
00324         LinAlg::Vector<REAL> X1;
00325 
00326         // Scatter global K, X and Y values into smaller groups
00327         _do_scatter(K,X,Y, K11,K12,K21,K22, Y2, X1);
00328 
00329         // Solve for {Y1} and {X2}
00330         LinAlg::Vector<REAL> TMP(X1);                // TMP <- X1
00331         LinAlg::Gemv(-1.0,K12,Y2,1.0,TMP);           // TMP <- -1.0*K12*Y2 + 1.0*X1
00332 
00333         // Call a linear solver for: TMP <- inv(K11)*TMP (K11 is lost)
00334         if (_idat.linSOLVER==InputData::lsLAPACK)
00335         {
00336 #if defined (USE_LAPACK) || defined (USE_GOTOBLAS)
00337             LinAlg::Gesv(K11, TMP); // TMP <- inv(K11)*TMP (K11 is lost)
00338 #else
00339             throw new Fatal(_("Solver::_inv_K_times_X: LAPACK (or GOTOBLAS) is not available (USE_LAPACK=false, or USE_GOTOBLAS=false)"));
00340 #endif
00341         }
00342         else if (_idat.linSOLVER==InputData::lsUMFPACK)
00343         {
00344             throw new Fatal(_("Solver::_inv_K_times_X: UMFPACK is not working yet"));
00345         }
00346         else if (_idat.linSOLVER==InputData::lsSUPERLU)
00347         {
00348             throw new Fatal(_("Solver::_inv_K_times_X: SUPERLU is not working yet"));
00349         }
00350         else throw new Fatal(_("Solver::_inv_K_times_X: linSOLVER is invalid"));
00351 
00352         LinAlg::Vector<REAL> & Y1 = TMP;             //  Y1 <- TMP (reference)
00353         LinAlg::Vector<REAL>   X2(Y2.Size());        // allocate X2
00354         LinAlg::Gemvpmv(1.0,K21,Y1, 1.0,K22,Y2, X2); //  X2 <- 1*K21*Y1 + 1*K22*Y2
00355 
00356         // Gather Y1, Y2, X1 and X2 into Y and X
00357         _do_gather(Y1,Y2, X1,X2, Y,X);
00358     //}
00359     //else if (_do_penalty)
00360     //{
00361     // Copy X to Res; neccessary for Gesv
00362     //   LinAlg::Copy(X, Y); // Y <- X
00363     //   K(ipresc,jpresc) <- Vpres*BIGNUM
00364     //   Gesv(K,Y) Y <- inv(K)*Y
00365     //}
00366 } // }}}
00367 
00368 inline void Solver::_do_scatter(LinAlg::Matrix<REAL> const & K,   // {{{
00369                                 LinAlg::Vector<REAL> const & X,
00370                                 LinAlg::Vector<REAL> const & Y,
00371                                 LinAlg::Matrix<REAL>       & K11, // Unknown_size x Unknown_size
00372                                 LinAlg::Matrix<REAL>       & K12, // Unknown_size x Prescribed_size
00373                                 LinAlg::Matrix<REAL>       & K21, // Prescribed_size x Unknown_size
00374                                 LinAlg::Matrix<REAL>       & K22, // Prescribed_size x Prescribed_size
00375                                 LinAlg::Vector<REAL>       & Y2,  // Prescribed_size
00376                                 LinAlg::Vector<REAL>       & X1)  // Unknown_size
00377 {
00378     // Unknown_size = us
00379     // Prescribed_size = ps
00380     int us = _a_udofs.size(); // unknown
00381     int ps = _a_pdofs.size(); // prescribed
00382 
00383     // Allocate matrices/vectors
00384     K11.Resize(us,us);
00385     K12.Resize(us,ps);
00386     K21.Resize(ps,us);
00387     K22.Resize(ps,ps);
00388     Y2.Resize(ps);
00389     X1.Resize(us);
00390     // Loop along Prescribed_size
00391     for (int ip=0; ip<ps; ++ip)
00392 
00393     // Loop along Unknown_size
00394     for (int iu=0; iu<us; ++iu)
00395     {
00396         // K11: Loop along Unknown_size
00397         for (int ju=0; ju<us; ++ju)
00398             K11(iu,ju) = K(_a_udofs[iu]->EqID, _a_udofs[ju]->EqID);
00399 
00400         // K12: Loop along Prescribed_size
00401         for (int jp=0; jp<ps; ++jp)
00402             K12(iu,jp) = K(_a_udofs[iu]->EqID, _a_pdofs[jp]->EqID);
00403 
00404         // X1
00405         X1(iu) = X(_a_udofs[iu]->EqID);
00406     }
00407 
00408     // Loop along Prescribed_size
00409     for (int ip=0; ip<ps; ++ip)
00410     {
00411         // K21: Loop along Unknown_size
00412         for (int ju=0; ju<us; ++ju)
00413             K21(ip,ju) = K(_a_pdofs[ip]->EqID, _a_udofs[ju]->EqID);
00414 
00415         // K22: Loop along Prescribed_size
00416         for (int jp=0; jp<ps; ++jp)
00417             K22(ip,jp) = K(_a_pdofs[ip]->EqID, _a_pdofs[jp]->EqID);
00418 
00419         // Y2
00420         Y2(ip) = Y(_a_pdofs[ip]->EqID);
00421     }
00422 } // }}}
00423 
00424 inline void Solver::_do_gather(LinAlg::Vector<REAL> const & Y1, // Unknown_size {{{
00425                                LinAlg::Vector<REAL> const & Y2, // Prescribed_size
00426                                LinAlg::Vector<REAL> const & X1, // Unknown_size
00427                                LinAlg::Vector<REAL> const & X2, // Prescribed_size
00428                                LinAlg::Vector<REAL>       & Y ,
00429                                LinAlg::Vector<REAL>       & X) 
00430 {
00431     // Unknown_size = us
00432     // Prescribed_size = ps
00433     int us = _a_udofs.size(); // unknown
00434     int ps = _a_pdofs.size(); // prescribed
00435 
00436     // Loop along Unknown_size
00437     for (int iu=0; iu<us; ++iu)
00438     {
00439         // Y1
00440         Y(_a_udofs[iu]->EqID) = Y1(iu);
00441 
00442         // X1
00443         X(_a_udofs[iu]->EqID) = X1(iu);
00444     }
00445 
00446     // Loop along Prescribed_size
00447     for (int ip=0; ip<ps; ++ip)
00448     {
00449         // Y2
00450         Y(_a_pdofs[ip]->EqID) = Y2(ip);
00451 
00452         // X2
00453         X(_a_pdofs[ip]->EqID) = X2(ip);
00454     }
00455 } // }}}
00456 
00457 inline void Solver::_backup_nodes_and_elements_state() // {{{
00458 {
00459     // ### Backup all nodes ############################################################################
00460     
00461     // Loop along Unknown_size
00462     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00463     {
00464          _U_bkp(_a_udofs[iu]->EqID) = _a_udofs[iu]->EssentialVal;
00465          _F_bkp(_a_udofs[iu]->EqID) = _a_udofs[iu]->NaturalVal;
00466     }
00467 
00468     // Loop along Prescribed_size
00469     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00470     {   
00471          _U_bkp(_a_pdofs[ip]->EqID) = _a_pdofs[ip]->EssentialVal;
00472          _F_bkp(_a_pdofs[ip]->EqID) = _a_pdofs[ip]->NaturalVal;
00473     }
00474 
00475     // ### Backup all elements #########################################################################
00476     
00477     // Loop along elements
00478     for (size_t i=0; i<_data.Elements.size(); ++i)
00479         _data.Elements[i]->BackupState();
00480 
00481     // #################################################################################################
00482 } // }}}
00483 
00484 inline void Solver::_update_nodes_and_elements_state(LinAlg::Vector<REAL> const & dU, LinAlg::Vector<REAL> & dF_int) // {{{
00485 {
00486     // ### Update all nodes #############################################################################
00487     
00488     // Loop along Unknown_size
00489     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00490         _a_udofs[iu]->EssentialVal += dU(_a_udofs[iu]->EqID);
00491 
00492     // Loop along Prescribed_size
00493     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00494         _a_pdofs[ip]->EssentialVal += dU(_a_pdofs[ip]->EqID);
00495 
00496     // ### Update all elements ##########################################################################
00497     
00498     // --- Setup dU values for all nodes and Zeroes _IncNatural values ----------------------------------
00499     
00500     // Loop along Unknown_size
00501     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00502     {
00503         _a_udofs[iu]->_IncEssenVal = dU(_a_udofs[iu]->EqID);
00504         _a_udofs[iu]->_IncNaturVal = 0.0; // Need to be set zero because will be output
00505     }
00506 
00507     // Loop along Prescribed_size
00508     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00509     {
00510         _a_pdofs[ip]->_IncEssenVal = dU(_a_pdofs[ip]->EqID);
00511         _a_pdofs[ip]->_IncNaturVal = 0.0; // Need to be set zero because will be output
00512     }
00513 
00514     // --- Update all elements --------------------------------------------------------------------------
00515     
00516     // Loop along elements
00517     for (size_t i=0; i<_data.Elements.size(); ++i)
00518         _data.Elements[i]->UpdateState(); // Read nodal values _IncEssential and write to _IncNatural
00519 
00520     // --- Read dF values (just calculated) from all nodes ----------------------------------------------
00521     
00522     // Loop along Unknown_size
00523     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00524         dF_int(_a_udofs[iu]->EqID) = _a_udofs[iu]->_IncNaturVal;
00525 
00526     // Loop along Prescribed_size
00527     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00528         dF_int(_a_pdofs[ip]->EqID) = _a_pdofs[ip]->_IncNaturVal;
00529 
00530     // ##################################################################################################
00531 } // }}}
00532 
00533 inline void Solver::_restore_nodes_and_elements_state() // {{{
00534 {
00535     // ### Restore all nodes ###########################################################################
00536     
00537     // Loop along Unknown_size
00538     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00539     {
00540         _a_udofs[iu]->EssentialVal = _U_bkp(_a_udofs[iu]->EqID);
00541           _a_udofs[iu]->NaturalVal = _F_bkp(_a_udofs[iu]->EqID);
00542     }
00543 
00544     // Loop along Prescribed_size
00545     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00546     {
00547         _a_pdofs[ip]->EssentialVal = _U_bkp(_a_pdofs[ip]->EqID);
00548           _a_pdofs[ip]->NaturalVal = _F_bkp(_a_pdofs[ip]->EqID);
00549     }
00550 
00551     // ### Restore all elements ########################################################################
00552     
00553     // Loop along elements
00554     for (size_t i=0; i<_data.Elements.size(); ++i)
00555         _data.Elements[i]->RestoreState();
00556 
00557     // #################################################################################################
00558 } // }}}
00559 
00560 inline REAL Solver::_norm_essential_vector() // {{{
00561 {
00562     REAL tmp=0.0;
00563     // Loop along Unknown_size
00564     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00565         tmp += pow(_a_udofs[iu]->EssentialVal,2.0);
00566 
00567     // Loop along Prescribed_size
00568     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00569         tmp += pow(_a_pdofs[ip]->EssentialVal,2.0);
00570 
00571     return sqrt(tmp);
00572 } // }}}
00573 
00574 inline REAL Solver::_norm_natural_vector() // {{{
00575 {
00576     REAL tmp=0.0;
00577     // Loop along Unknown_size
00578     for (size_t iu=0; iu<_a_udofs.size(); ++iu)
00579         tmp += pow(_a_udofs[iu]->NaturalVal,2.0);
00580 
00581     // Loop along Prescribed_size
00582     for (size_t ip=0; ip<_a_pdofs.size(); ++ip)
00583         tmp += pow(_a_pdofs[ip]->NaturalVal,2.0);
00584 
00585     return sqrt(tmp);
00586 } // }}}
00587 
00589 
00590 
00591 // Define a pointer to a function that makes (allocate) a new solver
00592 typedef Solver * (*SolverMakerPtr)(Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output);
00593 
00594 // Typdef of the array map that contains all the pointers to the functions that makes solvers
00595 typedef std::map<String, SolverMakerPtr, std::less<String> > SolverFactory_t;
00596 
00597 // Instantiate the array map that contains all the pointers to the functions that makes solvers
00598 SolverFactory_t SolverFactory;
00599 
00600 // Allocate a new solver according to a string giving the name of the solver
00601 Solver * AllocSolver(String const & SolverName, Array<String> const & SolverCtes, FEM::InputData const & ID, FEM::Data & data, FEM::Output & output) // {{{
00602 {
00603     SolverMakerPtr ptr=NULL;
00604     ptr = SolverFactory[SolverName];
00605     if (ptr==NULL)
00606         throw new Fatal(_("FEM::AllocSolver: There is no < %s > solver implemented in this library"), SolverName.c_str());
00607     return (*ptr)(SolverCtes, ID, data, output);
00608 } // }}}
00609 
00610 }; // namespace FEM
00611 
00612 #endif // MECHSYS_FEM_SOLVER_H
00613 
00614 // vim:fdm=marker

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