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

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