profmatr.cpp

Go to the documentation of this file.
00001 //############################################################################
00002 //#                                                                          #
00003 //#             /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/~~\              #
00004 //#            |                                          |____|             #
00005 //#            |                                          |                  #
00006 //#            |                                          |                  #
00007 //#            |                 B A S E                  |                  #
00008 //#            |                                          |                  #
00009 //#            |                                          |                  #
00010 //#            |              C L A S S E S               |                  #
00011 //#            |                                          |                  #
00012 //#            |                                          |                  #
00013 //#            |          C + +     S O U R C E           |                  #
00014 //#            |                                          |                  #
00015 //#            |                                          |                  #
00016 //#            |                                          |                  #
00017 //#            |                                          |                  #
00018 //#            |                                          |                  #
00019 //#         /~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/   |                  #
00020 //#        |                                         |    |                  #
00021 //#         \_________________________________________\__/                   #
00022 //#                                                                          #
00023 //#                                                                          #
00024 //############################################################################
00025 //
00026 //   "C makes it easy to shoot yourself in the foot, C++ makes it harder,
00027 //   but when you do, it blows away your whole leg" -- Bjarne Stroustrup
00028 //
00029 //##############################################################################
00030 #ifndef PROFMATR_CC
00031 #define PROFMATR_CC
00032 
00033 #include "profmatr.h"
00034 
00035 
00036 //##############################################################################
00037 //# COPYRIGHT (C):     :-))                                                    #
00038 //# PROJECT:           Object Oriented Finite Element Program                  #
00039 //# PURPOSE:                                                                   #
00040 //# CLASS:             profmatrix                                               #
00041 //#                                                                            #
00042 //# VERSION:                                                                   #
00043 //# LANGUAGE:          C++.ver >= 2.0 ( Borland C++ ver=3.10, SUN C++ ver=2.1 )#
00044 //# TARGET OS:         DOS || UNIX || . . .                                    #
00045 //# PROGRAMMER(S):     Boris Jeremic                                           #
00046 //#                                                                            #
00047 //#                                                                            #
00048 //# DATE:              September 12-13 '94 looking for the solver for symmetric#
00049 //#                                        and unsymmetric sparse matrices.    #
00050 //#                                        One solution is Taylor's profile    #
00051 //#                                        solver ( see FEM4ed by O.Z. and R.T.#
00052 //#                    September 27 '94 profile solver for symmetric and       #
00053 //#                                     Nonsymmetric systems works!            #
00054 //#                                     (from FEM4ed by O.Z. and R.T.)         #
00055 //#                                                                            #
00056 //#                                                                            #
00057 //##############################################################################
00058 // this one is based on Zienkiewicz's and Taylor's book!
00059 
00060 //##########################################################################
00061 
00062 
00063 //tempout//##########################################################################
00064 //tempout// create the structure and initialization of profilematrix!___Zhaohui 07-06-99
00065 //tempoutprofilematrix::profilematrix(FEModelData & FEMD, Brick3D * b3d, Node *  node)
00066 //tempout//skymatrix::skymatrix(FEModelData & FEMD, Finite_Element & FE)
00067 //tempout  {
00068 //tempout// create the structure:
00069 //tempout     pc_profilematrix_rep = new profilematrix_rep; // this 'new' is overloaded
00070 //tempout
00071 //tempout
00072 //tempout    int Number_of_DOFs = FEMD.get_number_of_DOFs();
00073 //tempout//    pc_profilematrix_rep->square_dim = Number_of_DOFs;
00074 //tempout// create ColumnHeight _________________________________________________
00075 //tempout// column height starts from 1 to  Number_of_DOFs.
00076 //tempout    pc_profilematrix_rep->columnheight = new int [Number_of_DOFs+1];
00077 //tempout      if (!pc_profilematrix_rep->columnheight)
00078 //tempout        {
00079 //tempout          ::printf("\a\nInsufficient memory for pc_skymatrix_rep->columnheight\n");
00080 //tempout          ::exit(1);
00081 //tempout        }
00082 //tempout    for (int count = 1 ; count <= Number_of_DOFs ; count++) 
00083 //tempout
00084 //tempout      //**** Changing 1 to 0 to set initial value of colheight. 
00085 //tempout      pc_profilematrix_rep->columnheight[count]=0;  
00086 //tempout
00087 //tempout    int Number_of_Elements = FEMD.get_number_of_Bricks();
00088 //tempout
00089 //tempout    int II = 0;
00090 //tempout    int *LM = NULL;
00091 //tempout    int ME = 0;
00092 //tempout
00093 //tempout    int Number_of_DOFs_for_brick = 24;
00094 //tempout
00095 //tempout    for (int el_count = 1 ; el_count <= Number_of_Elements ; el_count++)
00096 //tempout      {
00097 //tempout        b3d[el_count].set_LM(node);
00098 //tempout//        b3d[el_count].reportLM("LM");
00099 //tempout      }
00100 //tempout
00101 //tempout// KJBathe: Page 1002 sub COLHT
00102 //tempout    int LS = 1000000;
00103 //tempout    int temp=0;
00104 //tempout
00105 //tempout    for (int el_cnt =1 ; el_cnt <= Number_of_Elements ; el_cnt++)
00106 //tempout      {
00107 //tempout        LS = 1000000; 
00108 //tempout        LM = b3d[el_cnt].get_LM();
00109 //tempout        for (int count01 = 0 ; count01 < Number_of_DOFs_for_brick ; count01++)
00110 //tempout          {
00111 //tempout            if (LM[count01] !=0 )
00112 //tempout              {
00113 //tempout//              ::printf("+++++++ LM[%d]= %d  LS = %d \n", count01, LM[count01],  LS);
00114 //tempout                temp =  LS;
00115 //tempout//              ::printf("temp = %d  LM[%d]= %d \n", temp, count01, LM[count01]);
00116 //tempout                temp = LM[count01] - temp;
00117 //tempout//              ::printf("temp = %d  LM[%d]= %d  LS = %d \n", temp, count01, LM[count01],  LS);
00118 //tempout                if ( temp < 0 ) 
00119 //tempout                  {
00120 //tempout                     LS = LM[count01];
00121 //tempout//                 ::printf("(LM[count01]-LS)<0->> LM[%d]= %d  LS = %d \n", count01, LM[count01],  LS);
00122 //tempout                  }
00123 //tempout
00124 //tempout              }
00125 //tempout          // getchar();
00126 //tempout          
00127 //tempout          }
00128 //tempout      
00129 //tempout      
00130 //tempout        for (int count02 = 0 ; count02 < Number_of_DOFs_for_brick ; count02++)
00131 //tempout          {
00132 //tempout            II = LM[count02];
00133 //tempout          // ::printf("II= %d  LM[%d] = %d \n", II,count02, LM[count02] );
00134 //tempout
00135 //tempout            if (II!=0) 
00136 //tempout              {
00137 //tempout                ME = II-LS;
00138 //tempout         //  ::printf("ME= %d  II = %d  LS = %d \n", ME, II, LS );
00139 //tempout
00140 //tempout         //  ::printf("ME= %d  II = %d  ColumnHeight[%d] = %d \n", ME, II, II, ColumnHeight[II]);
00141 //tempout              if (ME > pc_profilematrix_rep->columnheight[II]) 
00142 //tempout                {
00143 //tempout                  pc_profilematrix_rep->columnheight[II] = ME;
00144 //tempout           //  ::printf("ME > ColumnHeight[II] ->> ME= %d  ColumnHeight[%d] = %d \n", ME, II, ColumnHeight[II]);
00145 //tempout           //  getchar();
00146 //tempout                  }
00147 //tempout              }
00148 //tempout         }
00149 //tempout      
00150 //tempout//        ::printf("IN colheigth = \n");
00151 //tempout
00152 //tempout//    for (int count03 = 1 ; count03 <= Number_of_DOFs ; count03++)
00153 //tempout//      {
00154 //tempout//        ::printf(" %d ",  pc_profilematrix_rep->columnheight[count03] );
00155 //tempout//      }
00156 //tempout//      getchar();
00157 //tempout      
00158 //tempout
00159 //tempout      }
00160 //tempout
00161 //tempout
00162 //tempout
00163 //tempout
00164 //tempout//        ::printf(" \n ------+------ \n ");
00165 //tempout
00166 //tempout//--    //KJBathe pp 1002
00167 //tempout
00168 //tempout//// Create the pc_profilematrix->jp vector -----Zhaohui
00169 //tempout// jp[i], i starts from 0 to Number_of_DOFs - 1 !!
00170 //tempout// column height [i], i starts from 1 to Number_of_DOFs !!
00171 //tempout    pc_profilematrix_rep->jp = new int [Number_of_DOFs];
00172 //tempout    if (!pc_profilematrix_rep->jp)
00173 //tempout      {
00174 //tempout        ::printf("\a\nInsufficient memory for JP vector\n");
00175 //tempout        ::exit(1);
00176 //tempout      }
00177 //tempout    pc_profilematrix_rep->jp[ 0 ] = 0;
00178 //tempout    for (int count04 = 1 ; count04 < Number_of_DOFs ; count04++)
00179 //tempout      {
00180 //tempout       pc_profilematrix_rep->jp[count04]  = 
00181 //tempout         pc_profilematrix_rep->jp[count04 - 1] + pc_profilematrix_rep->columnheight[count04+1] ;
00182 //tempout      }
00183 //tempout    
00184 //tempout    int Numb_of_DOF = FEMD.get_number_of_DOFs(); 
00185 //tempout
00186 //tempout// set value for member of pc_profilematrix_rep---Zhaohui
00187 //tempout    pc_profilematrix_rep->neq = Numb_of_DOF;
00188 //tempout    pc_profilematrix_rep->total_numb = pc_profilematrix_rep->jp[Numb_of_DOF-1];
00189 //tempout    pc_profilematrix_rep->flag = 'N';
00190 //tempout
00191 //tempout//    ::printf("\n\n Profile____JP = \n");
00192 //tempout//    for (int count05 = 0 ; count05 < Number_of_DOFs ; count05++)
00193 //tempout//      {
00194 //tempout//       ::printf(" %d ",  pc_profilematrix_rep->jp[count05] );
00195 //tempout//      }
00196 //tempout
00197 //tempout// Initialization and allocation memory of profilematrix____zhaohui
00198 //tempout//  void profilematrix::profile_init( FEModelData      & FEMD)
00199 //tempout//    {
00200 //tempout    int length_of_AL = pc_profilematrix_rep->total_numb;
00201 //tempout
00202 //tempout// allocate memory for the actual profilematrix as profilematrix
00203 //tempout    pc_profilematrix_rep->al = new double [(size_t) length_of_AL];
00204 //tempout      if (!pc_profilematrix_rep->al)
00205 //tempout        { printf("\a\nInsufficient memory for AL\n"); exit(1);}
00206 //tempout    pc_profilematrix_rep->ad = new double [(size_t) Numb_of_DOF];
00207 //tempout      if (!pc_profilematrix_rep->ad)
00208 //tempout        { printf("\a\nInsufficient memory for AD\n"); exit(1);}
00209 //tempout    pc_profilematrix_rep->au = new double [(size_t) length_of_AL];
00210 //tempout      if (!pc_profilematrix_rep->au)
00211 //tempout        { printf("\a\nInsufficient memory for AU\n"); exit(1);}
00212 //tempout
00213 //tempout    for (int I = 0 ; I < length_of_AL ; I++)   // Initializing AL, AU.
00214 //tempout      {
00215 //tempout        pc_profilematrix_rep->al[I] = 0.0;
00216 //tempout        pc_profilematrix_rep->au[I] = 0.0;
00217 //tempout       }
00218 //tempout    for (int I = 0 ; I < Numb_of_DOF ; I++)   // Initializing AD.
00219 //tempout      {
00220 //tempout        pc_profilematrix_rep->ad[I] = 0.0;
00221 //tempout       }
00222 //tempout
00223 //tempout
00224 //tempout    pc_profilematrix_rep->n = 1;  // so far, there's one reference
00225 //tempout
00226 //tempout
00227 //tempout// Initialization and allocation memory of profilematrix____zhaohui
00228 //tempout
00229 //tempout//--
00230 //tempout//--   int Total_K_length = pc_profilematrix_rep->maxa[Number_of_DOFs+1];
00231 //tempout//--
00232 //tempout//--    pc_profilematrix_rep->data = new double [Total_K_length+1];
00233 //tempout//--
00234 //tempout//--      if (!pc_profilematrix_rep->data)
00235 //tempout//--        {
00236 //tempout//--          ::printf("\a\nInsufficient memory for pc_profilematrix_rep->data\n");
00237 //tempout//--          ::exit(1);
00238 //tempout//--        }
00239 //tempout//--    for (int count08 = 1 ; count08 <= Number_of_DOFs ; count08++) 
00240 //tempout//--      pc_profilematrix_rep->data[count08]=0;
00241 //tempout//--
00242 //tempout
00243 //tempout
00244 //tempout  }
00245 
00247 
00248 
00249 
00250 profilematrix::profilematrix(int matrix_order,
00251                              int *jp_init,
00252                              char flag_init,
00253                              double *au_init_val,
00254                              double *al_init_val,
00255                              double *ad_init_val)
00256   {
00257  // create the structure:
00258     pc_profilematrix_rep = new profilematrix_rep; // this 'new' is overloaded
00259 
00260     pc_profilematrix_rep->neq = matrix_order;
00261 
00262 // get space for the JP vector
00263     pc_profilematrix_rep->jp = new int[matrix_order];
00264 // put all jp_init's in the jp
00265     for ( int j=0 ; j<pc_profilematrix_rep->neq ; j++ )
00266       pc_profilematrix_rep->jp[j] = jp_init[j];
00267 
00268     pc_profilematrix_rep->total_numb = pc_profilematrix_rep->jp[matrix_order-1];
00269 
00270 // set flag for Symmetry of Nonsymmetry
00271     pc_profilematrix_rep->flag = flag_init;
00272 
00273 // allocate memory for the actual profilematrix as profilematrix
00274     pc_profilematrix_rep->au = new double [(size_t) pc_profilematrix_rep->total_numb];
00275       if (!pc_profilematrix_rep->au)
00276         {
00277           ::printf("\a\nInsufficient memory for pc_profilematrix_rep->au\n");
00278           ::exit(1);
00279         }
00280 
00281     if ( pc_profilematrix_rep->flag == 'N' )
00282       {
00283         pc_profilematrix_rep->al = new double [(size_t) pc_profilematrix_rep->total_numb];
00284           if (!pc_profilematrix_rep->al)
00285             {
00286               ::printf("\a\nInsufficient memory for pc_profilematrix_rep->al\n");
00287               ::exit(1);
00288             }
00289       }
00290     else if ( pc_profilematrix_rep->flag == 'S' )
00291       {
00292         pc_profilematrix_rep->al = pc_profilematrix_rep->au;
00293       }
00294     else
00295       {
00296         ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00297       }
00298 
00299     pc_profilematrix_rep->ad = new double [(size_t) pc_profilematrix_rep->neq];
00300       if (!pc_profilematrix_rep->ad)
00301         {
00302           ::printf("\a\nInsufficient memory for pc_profilematrix_rep->ad\n");
00303           ::exit(1);
00304         }
00305 
00306 
00307     pc_profilematrix_rep->n = 1;  // so far, there's one reference
00308 
00309 // this constructors is just for testing purposes.
00310 // The real one is to be initialized from 0.0 init_vals and then
00311 // class stiffness matrix those values are to be altered!!!!!!!!!!!!!!!!!!!!!!!!
00312     for ( int iau=0 ; iau<pc_profilematrix_rep->total_numb ; iau++ )
00313       pc_profilematrix_rep->au[iau] = au_init_val[iau];
00314 
00315     for ( int iad=0 ; iad<pc_profilematrix_rep->neq ; iad++ )
00316       pc_profilematrix_rep->ad[iad] = ad_init_val[iad];
00317 
00318     if ( pc_profilematrix_rep->flag == 'N' )
00319       {
00320         for ( int ial=0 ; ial<pc_profilematrix_rep->total_numb ; ial++ )
00321           pc_profilematrix_rep->al[ial] = al_init_val[ial];
00322       }
00323 
00324 
00325   }
00326 
00327 //##########################################################################
00328 // overloaded. Different calling methods
00329 profilematrix::profilematrix(int matrix_order,
00330                              int *jp_init,
00331                              char flag_init,
00332                              double au_init_val,
00333                              double al_init_val,
00334                              double ad_init_val)
00335   {
00336  // create the structure:
00337     pc_profilematrix_rep = new profilematrix_rep; // this 'new' is overloaded
00338 
00339     pc_profilematrix_rep->neq = matrix_order;
00340 
00341 // get space for the JP vector
00342     pc_profilematrix_rep->jp = new int[matrix_order];
00343 // put all jp_init's in the jp
00344     for ( int j=0 ; j<pc_profilematrix_rep->neq ; j++ )
00345       pc_profilematrix_rep->jp[j] = jp_init[j];
00346 
00347     pc_profilematrix_rep->total_numb = pc_profilematrix_rep->jp[matrix_order-1];
00348 
00349 // set flag for Symmetry of Nonsymmetry
00350     pc_profilematrix_rep->flag = flag_init;
00351 
00352 // allocate memory for the actual profilematrix as profilematrix
00353     pc_profilematrix_rep->au = new double [(size_t) pc_profilematrix_rep->total_numb];
00354       if (!pc_profilematrix_rep->au)
00355         {
00356           ::printf("\a\nInsufficient memory for pc_profilematrix_rep->au\n");
00357           ::exit(1);
00358         }
00359 
00360     if ( pc_profilematrix_rep->flag == 'N' )
00361       {
00362         pc_profilematrix_rep->al = new double [(size_t) pc_profilematrix_rep->total_numb];
00363           if (!pc_profilematrix_rep->al)
00364             {
00365               ::printf("\a\nInsufficient memory for pc_profilematrix_rep->al\n");
00366               ::exit(1);
00367             }
00368       }
00369     else if ( pc_profilematrix_rep->flag == 'S' )
00370       {
00371         pc_profilematrix_rep->al = pc_profilematrix_rep->au;
00372       }
00373     else
00374       {
00375         ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00376       }
00377 
00378     pc_profilematrix_rep->ad = new double [(size_t) pc_profilematrix_rep->neq];
00379       if (!pc_profilematrix_rep->ad)
00380         {
00381           ::printf("\a\nInsufficient memory for pc_profilematrix_rep->ad\n");
00382           ::exit(1);
00383         }
00384 
00385 
00386     pc_profilematrix_rep->n = 1;  // so far, there's one reference
00387 
00388 // The real one is to be initialized from 0.0 init_vals and then
00389 // class stiffness matrix those values are to be altered!!!!!!!!!!!!!!!!!!!!!!!!
00390     for ( int iau=0 ; iau<pc_profilematrix_rep->total_numb ; iau++ )
00391       pc_profilematrix_rep->au[iau] = au_init_val;
00392 
00393     for ( int iad=0 ; iad<pc_profilematrix_rep->neq ; iad++ )
00394       pc_profilematrix_rep->ad[iad] = ad_init_val;
00395 
00396     if ( pc_profilematrix_rep->flag == 'N' )
00397       {
00398         for ( int ial=0 ; ial<pc_profilematrix_rep->total_numb ; ial++ )
00399           pc_profilematrix_rep->al[ial] = al_init_val;
00400       }
00401 
00402 
00403   }
00404 
00405 //##############################################################################
00406 profilematrix::profilematrix(const profilematrix & x)   // copy initializer
00407  {
00408   x.pc_profilematrix_rep->n++; // we're adding another reference.
00409   pc_profilematrix_rep = x.pc_profilematrix_rep;  // point to the new profilematrix_rep.
00410  }
00411 
00412 
00413 
00414 //##########################################################################
00415 profilematrix::~profilematrix()
00416   {
00417     if (--pc_profilematrix_rep->n == 0)  // if reference count  goes to 0
00418   {
00419 // DEallocate memory of the actual nDarray
00420 //    delete [pc_nDarray_rep->pc_nDarray_rep->total_numb] pc_nDarray_rep->pd_nDdata;
00421 //  see ELLIS & STROUSTRUP $18.3
00422 //  and note on the p.65($5.3.4)
00423 //  and the page 276 ($12.4)
00424     delete [] pc_profilematrix_rep->au;
00425     delete [] pc_profilematrix_rep->ad;
00426     if ( pc_profilematrix_rep->flag == 'N' )
00427       {
00428         delete [] pc_profilematrix_rep->al;
00429       }
00430     delete [] pc_profilematrix_rep->jp;
00431     //delete pc_profilematrix_rep;
00432   }
00433 }
00434 
00436 profilematrix & profilematrix::operator=(const profilematrix & rval)
00437   {
00438     rval.pc_profilematrix_rep->n++; // we're adding another reference.
00439 //    rval.reference_count(+1);  // tell the rval it has another reference
00440 // It is important to increment the reference_counter in the new
00441 // tensor before decrementing the reference_counter in the
00442 // old tensor_rep to ensure proper operation when assigning a
00443 // tensor_rep to itself ( after ARKoenig JOOP May/June '90 )
00444 // clean up current value;
00445     if( reference_count(-1) == 0)  // if nobody else is referencing us.
00446       {
00447         delete [] pc_profilematrix_rep->au;
00448         delete [] pc_profilematrix_rep->ad;
00449         if ( pc_profilematrix_rep->flag == 'N' )
00450           {
00451             delete [] pc_profilematrix_rep->al;
00452           }
00453         delete [] pc_profilematrix_rep->jp;
00454         delete pc_profilematrix_rep;
00455       }
00456 // connect to new value
00457     pc_profilematrix_rep = rval.pc_profilematrix_rep;// point at the rval profilematrix_rep
00458 
00459     return *this;
00460   }
00461 
00462 //##########################################################################
00463 int profilematrix::dimension_of_profile_M(void) const // dimension of profile matrix
00464   {
00465     return pc_profilematrix_rep->neq;
00466   }
00467 
00468 //##########################################################################
00469 int * profilematrix::get_jp(void) const  // get pointer to array of
00470   {                                      // Locations of Diagonals
00471     return pc_profilematrix_rep->jp;
00472   }
00473 
00474 //##########################################################################
00475 //Zhaohui  added to set the max and min element
00476 double profilematrix::get_max(void) // 
00477  {                                                 
00478     double max_element = -1000000.0;
00479     for (int i =0; i< pc_profilematrix_rep->neq; i++)
00480      //{
00481         if (pc_profilematrix_rep->ad[i] > max_element)
00482            max_element = pc_profilematrix_rep->ad[i];
00483 //       else if (pc_profilematrix_rep->ad[i] < min_element)
00484 //           min_element = pc_profilematrix_rep->ad[i];
00485 
00486       //}
00487     //for ( int i=0 ; i<pc_profilematrix_rep->total_numb ; i++ )
00488     // {
00489     //    if (pc_profilematrix_rep->au[i] > pc_profilematrix_rep->max_element)
00490     //       pc_profilematrix_rep->max_element = pc_profilematrix_rep->au[i];
00491     //   else if (pc_profilematrix_rep->au[i] < pc_profilematrix_rep->min_element)
00492     //       pc_profilematrix_rep->min_element = pc_profilematrix_rep->au[i];
00493     //
00494     //  }
00495     //for ( int i=0 ; i<pc_profilematrix_rep->total_numb ; i++ )
00496     // {
00497     //    if (pc_profilematrix_rep->al[i] > pc_profilematrix_rep->max_element)
00498     //       pc_profilematrix_rep->max_element = pc_profilematrix_rep->al[i];
00499     //   else if (pc_profilematrix_rep->al[i] < pc_profilematrix_rep->min_element)
00500     //       pc_profilematrix_rep->min_element = pc_profilematrix_rep->al[i];
00501     //
00502     //  }
00503 
00504     return max_element;
00505  }
00506 
00507 
00508 //##########################################################################
00509 //Zhaohui  added to set the max-element in diagonal of eqn_no_shake!
00510 void profilematrix::set_penalty_element(int *eqn_no_shake, int no_of_shake, double max_element) 
00511  {                                                  
00512  //double scale = 100000.0;
00513  for (int count00 = 0 ; count00 < no_of_shake; count00++)
00514   {
00515 //     ::printf("mass_pen before :  %+10.3e, %d ", pc_profilematrix_rep->ad[eqn_no_shake[count00]-1] , eqn_no_shake[count00]);
00516 //     pc_profilematrix_rep->ad[eqn_no_shake[count00]] = max_element;
00517      // correct for eq_no =1, 2 ,..., but ad starts from 0.
00518      pc_profilematrix_rep->ad[eqn_no_shake[count00]-1] = max_element;
00519 //     ::printf("mass_pen after  :  %+10.3e, %d ", pc_profilematrix_rep->ad[eqn_no_shake[count00]-1] , eqn_no_shake[count00]);
00520   }
00521 }
00522 
00523 //##########################################################################
00524 //double  profilematrix::get_max(void)        // get pointer to array of
00525 //  {                                      // Locations of Diagonals
00526 //    return pc_profilematrix_rep->max_element;
00527 //  }
00528 //##########################################################################
00529 //double  profilematrix::get_min(void)        // get pointer to array of
00530 //  {                                      // Locations of Diagonals
00531 //    return pc_profilematrix_rep->min_element;
00532 //  }
00533 //
00535 // profilematrix addition
00536 profilematrix& profilematrix::operator+=(const profilematrix & rval)
00537   {
00538     long int this_total_numb = this->pc_profilematrix_rep->total_numb;
00539     long int rval_total_numb =  rval.pc_profilematrix_rep->total_numb;
00540 //    this_total_numb = 696;
00541 //    rval_total_numb = 696;
00542 
00543     if(this_total_numb != rval_total_numb)
00544       {
00545         ::printf("\a\nprofilematrixs of different sizes: += not YET possible\n");
00546         ::exit ( 1 );
00547       }
00548 
00549 // Copy *this if necessary
00550     if ( this->pc_profilematrix_rep->n > 1 )// see ARK in JOOP may/june '90
00551       {                                    // "Letter From a Newcomer"
00552 // create the structure:
00553         profilematrix_rep * New_pc_profilematrix_rep = new profilematrix_rep; // this 'new' is overloaded
00554 
00555         New_pc_profilematrix_rep->neq = this->pc_profilematrix_rep->neq ;
00556 
00557 // get space for the JP vector
00558         New_pc_profilematrix_rep->jp = new int[New_pc_profilematrix_rep->neq];
00559 // put all jp_init's in the jp
00560         for ( int j=0 ; j<this->pc_profilematrix_rep->neq ; j++ )
00561           New_pc_profilematrix_rep->jp[j] = this->pc_profilematrix_rep->jp[j];
00562 
00563         New_pc_profilematrix_rep->total_numb = this->pc_profilematrix_rep->total_numb;
00564 
00565 // set flag for Symmetry of Nonsymmetry
00566         New_pc_profilematrix_rep->flag = this->pc_profilematrix_rep->flag;
00567 
00568 // allocate memory for the actual profilematrix as profilematrix
00569         New_pc_profilematrix_rep->au = new double [(size_t) New_pc_profilematrix_rep->total_numb];
00570           if (!New_pc_profilematrix_rep->au)
00571             {
00572               ::printf("\a\nInsufficient memory for New_pc_profilematrix_rep->au\n");
00573               ::exit(1);
00574             }
00575 
00576         if ( New_pc_profilematrix_rep->flag == 'N' )
00577           {
00578             New_pc_profilematrix_rep->al = new double [(size_t) New_pc_profilematrix_rep->total_numb];
00579               if (!New_pc_profilematrix_rep->al)
00580                 {
00581                   ::printf("\a\nInsufficient memory for New_pc_profilematrix_rep->al\n");
00582                   ::exit(1);
00583                 }
00584           }
00585         else if ( New_pc_profilematrix_rep->flag == 'S' )
00586           {
00587             New_pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00588           }
00589         else
00590           {
00591             ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00592           }
00593 
00594         New_pc_profilematrix_rep->ad = new double [(size_t) New_pc_profilematrix_rep->neq];
00595           if (!New_pc_profilematrix_rep->ad)
00596             {
00597               ::printf("\a\nInsufficient memory for New_pc_profilematrix_rep->ad\n");
00598               ::exit(1);
00599             }
00600 
00601         New_pc_profilematrix_rep->n = 1;  // so far, there's one reference
00602 
00603 // The real one is to be initialized from 0.0 init_vals and then
00604 // class stiffness matrix those values are to be altered!!!!!!!!!!!!!!!!!!!!!!!!
00605 //        for ( int iau=0 ; iau<New_pc_profilematrix_rep->total_numb ; iau++ )
00606         for ( int iau=0 ; iau<this_total_numb ; iau++ )
00607           New_pc_profilematrix_rep->au[iau] = this->pc_profilematrix_rep->au[iau];
00608 
00609         for ( int iad=0 ; iad<New_pc_profilematrix_rep->neq ; iad++ )
00610           New_pc_profilematrix_rep->ad[iad] = this->pc_profilematrix_rep->ad[iad];
00611 
00612         if ( New_pc_profilematrix_rep->flag == 'N' )
00613           {
00614             for ( int ial=0 ; ial<this_total_numb ; ial++ )
00615               New_pc_profilematrix_rep->al[ial] = this->pc_profilematrix_rep->al[ial];
00616           }
00617         else if ( New_pc_profilematrix_rep->flag == 'S' )
00618           {
00619             New_pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00620           }
00621         else
00622           {
00623             ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00624           }
00625 
00626 
00627 //??????????????????
00628 //        this->pc_profilematrix_rep->total_numb--;
00629         this->pc_profilematrix_rep = New_pc_profilematrix_rep;
00630 //..............................................................................
00631       }
00632 // I can add this two profilematrices just as a simple vectors:
00633 //    for (int kau=0 ; kau<this->pc_profilematrix_rep->total_numb ; kau++)
00634     for (int kau=0 ; kau<this_total_numb ; kau++)
00635       this->pc_profilematrix_rep->au[kau] += rval.pc_profilematrix_rep->au[kau];
00636     for (int kad=0 ; kad<this->pc_profilematrix_rep->neq ; kad++)
00637       this->pc_profilematrix_rep->ad[kad] += rval.pc_profilematrix_rep->ad[kad];
00638     if ( this->pc_profilematrix_rep->flag == 'N' )
00639       {
00640         for ( int kal=0 ; kal<this_total_numb ; kal++ )
00641          this->pc_profilematrix_rep->al[kal] += rval.pc_profilematrix_rep->al[kal];
00642       }
00643 //..// this is OK
00644 //..    else if ( this->pc_profilematrix_rep->flag == 'S' )
00645 //..      {
00646 //..        this->pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00647 //..      }
00648 //..    else
00649 //..      {
00650 //..        ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00651 //..      }
00652 //..
00653     return *this;
00654   }
00655 
00656 
00657 //##############################################################################
00658 // profilematrix addition
00659 profilematrix operator+(const profilematrix & lval, const profilematrix & rval)
00660   {
00661     profilematrix result(lval);
00662     result += rval;
00663     return result;
00664   }
00665 
00666 
00667 //##############################################################################
00668 // scalar addition
00669 profilematrix profilematrix::operator+( double rval)
00670   {
00671 // construct profilematrix using the same control numbers as for the
00672 // original one.
00673     profilematrix add(this->pc_profilematrix_rep->neq,
00674                       this->pc_profilematrix_rep->jp,
00675                       this->pc_profilematrix_rep->flag,
00676                       this->pc_profilematrix_rep->al,
00677                       this->pc_profilematrix_rep->au,
00678                       this->pc_profilematrix_rep->ad);
00679 
00680 // I can add this two profilematrices just as a simple vectors:
00681     for (int kau=0 ; kau<this->pc_profilematrix_rep->total_numb ; kau++)
00682       add.pc_profilematrix_rep->au[kau] += rval;
00683     for (int kad=0 ; kad<this->pc_profilematrix_rep->neq ; kad++)
00684       add.pc_profilematrix_rep->ad[kad] += rval;
00685     if ( this->pc_profilematrix_rep->flag == 'N' )
00686       {
00687         for ( int kal=0 ; kal<this->pc_profilematrix_rep->total_numb ; kal++ )
00688          add.pc_profilematrix_rep->al[kal] += rval;
00689       }
00690 //..// thsi is OK!
00691 //..    else if ( this->pc_profilematrix_rep->flag == 'S' )
00692 //..      {
00693 //..        this->pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00694 //..      }
00695 //..    else
00696 //..      {
00697 //..        ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00698 //..      }
00699 
00700     return add;
00701  }
00702 
00703 //##############################################################################
00704 // profilematrix substraction
00705 profilematrix& profilematrix::operator-=(const profilematrix & rval)
00706   {
00707     long int this_total_numb = this->pc_profilematrix_rep->total_numb;
00708     long int rval_total_numb =  rval.pc_profilematrix_rep->total_numb;
00709 
00710     if(this_total_numb != rval_total_numb)
00711       {
00712         ::printf("\a\nprofilematrixs of different sizes: -= not YET possible\n");
00713         ::exit ( 1 );
00714       }
00715 
00716 // Copy *this if necessary
00717     if ( this->pc_profilematrix_rep->n > 1 )// see ARK in JOOP may/june '90
00718       {                                    // "Letter From a Newcomer"
00719 // create the structure:
00720         profilematrix_rep * New_pc_profilematrix_rep = new profilematrix_rep; // this 'new' is overloaded
00721 
00722         New_pc_profilematrix_rep->neq = this->pc_profilematrix_rep->neq ;
00723 
00724 // get space for the JP vector
00725         New_pc_profilematrix_rep->jp = new int[New_pc_profilematrix_rep->neq];
00726 // put all jp_init's in the jp
00727         for ( int j=0 ; j<this->pc_profilematrix_rep->neq ; j++ )
00728           New_pc_profilematrix_rep->jp[j] = this->pc_profilematrix_rep->jp[j];
00729 
00730         New_pc_profilematrix_rep->total_numb = New_pc_profilematrix_rep->total_numb;
00731 
00732 // set flag for Symmetry of Nonsymmetry
00733         New_pc_profilematrix_rep->flag = this->pc_profilematrix_rep->flag;
00734 
00735 // allocate memory for the actual profilematrix as profilematrix
00736         New_pc_profilematrix_rep->au = new double [(size_t) New_pc_profilematrix_rep->total_numb];
00737           if (!New_pc_profilematrix_rep->au)
00738             {
00739               ::printf("\a\nInsufficient memory for New_pc_profilematrix_rep->au\n");
00740               ::exit(1);
00741             }
00742 
00743         if ( New_pc_profilematrix_rep->flag == 'N' )
00744           {
00745             New_pc_profilematrix_rep->al = new double [(size_t) New_pc_profilematrix_rep->total_numb];
00746               if (!New_pc_profilematrix_rep->al)
00747                 {
00748                   ::printf("\a\nInsufficient memory for New_pc_profilematrix_rep->al\n");
00749                   ::exit(1);
00750                 }
00751           }
00752         else if ( New_pc_profilematrix_rep->flag == 'S' )
00753           {
00754             New_pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00755           }
00756         else
00757           {
00758             ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00759           }
00760 
00761         New_pc_profilematrix_rep->ad = new double [(size_t) New_pc_profilematrix_rep->neq];
00762           if (!New_pc_profilematrix_rep->ad)
00763             {
00764               ::printf("\a\nInsufficient memory for New_pc_profilematrix_rep->ad\n");
00765               ::exit(1);
00766             }
00767 
00768         New_pc_profilematrix_rep->n = 1;  // so far, there's one reference
00769 
00770 // The real one is to be initialized from 0.0 init_vals and then
00771 // class stiffness matrix those values are to be altered!!!!!!!!!!!!!!!!!!!!!!!!
00772         for ( int iau=0 ; iau<New_pc_profilematrix_rep->total_numb ; iau++ )
00773           New_pc_profilematrix_rep->au[iau] = this->pc_profilematrix_rep->au[iau];
00774 
00775         for ( int iad=0 ; iad<New_pc_profilematrix_rep->neq ; iad++ )
00776           New_pc_profilematrix_rep->au[iad] = this->pc_profilematrix_rep->ad[iad];
00777 
00778         if ( New_pc_profilematrix_rep->flag == 'N' )
00779           {
00780             for ( int ial=0 ; ial<New_pc_profilematrix_rep->total_numb ; ial++ )
00781               New_pc_profilematrix_rep->al[ial] = this->pc_profilematrix_rep->al[ial];
00782           }
00783         else if ( New_pc_profilematrix_rep->flag == 'S' )
00784           {
00785             New_pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00786           }
00787         else
00788           {
00789             ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00790           }
00791 
00792         this->pc_profilematrix_rep->total_numb--;
00793         this->pc_profilematrix_rep = New_pc_profilematrix_rep;
00794 //..............................................................................
00795       }
00796 // I can add this two profilematrices just as a simple vectors:
00797     for (int kau=0 ; kau<this->pc_profilematrix_rep->total_numb ; kau++)
00798       this->pc_profilematrix_rep->au[kau] -= rval.pc_profilematrix_rep->au[kau];
00799     for (int kad=0 ; kad<this->pc_profilematrix_rep->neq ; kad++)
00800       this->pc_profilematrix_rep->ad[kad] -= rval.pc_profilematrix_rep->ad[kad];
00801     if ( this->pc_profilematrix_rep->flag == 'N' )
00802       {
00803         for ( int kal=0 ; kal<this->pc_profilematrix_rep->total_numb ; kal++ )
00804          this->pc_profilematrix_rep->al[kal] -= rval.pc_profilematrix_rep->al[kal];
00805       }
00806 //..// this is OK!
00807 //..    else if ( this->pc_profilematrix_rep->flag == 'S' )
00808 //..      {
00809 //..        this->pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00810 //..      }
00811 //..    else
00812 //..      {
00813 //..        ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00814 //..      }
00815 
00816     return *this;
00817   }
00818 
00819 
00820 //##############################################################################
00821 // profilematrix substraction
00822 profilematrix operator-(const profilematrix & lval, const profilematrix & rval)
00823   {
00824     profilematrix result(lval);
00825     result -= rval;
00826     return result;
00827   }
00828 
00829 
00830 //##############################################################################
00831 // scalar substraction
00832 profilematrix profilematrix::operator-( double rval)
00833   {
00834 // construct profilematrix using the same control numbers as for the
00835 // original one.
00836     profilematrix sub(this->pc_profilematrix_rep->neq,
00837                       this->pc_profilematrix_rep->jp,
00838                       this->pc_profilematrix_rep->flag,
00839                       this->pc_profilematrix_rep->al,
00840                       this->pc_profilematrix_rep->au,
00841                       this->pc_profilematrix_rep->ad);
00842 
00843 // I can add this two profilematrices just as a simple vectors:
00844     for (int kau=0 ; kau<this->pc_profilematrix_rep->total_numb ; kau++)
00845       sub.pc_profilematrix_rep->au[kau] -= rval;
00846     for (int kad=0 ; kad<this->pc_profilematrix_rep->neq ; kad++)
00847       sub.pc_profilematrix_rep->ad[kad] -= rval;
00848     if ( this->pc_profilematrix_rep->flag == 'N' )
00849       {
00850         for ( int kal=0 ; kal<this->pc_profilematrix_rep->total_numb ; kal++ )
00851          sub.pc_profilematrix_rep->al[kal] -= rval;
00852       }
00853 //..// Thsi is OK!
00854 //..    else if ( this->pc_profilematrix_rep->flag == 'S' )
00855 //..      {
00856 //..        this->pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00857 //..      }
00858 //..    else
00859 //..      {
00860 //..        ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00861 //..      }
00862 
00863     return sub;
00864  }
00865 
00866 //##############################################################################
00867 // profilematrix multiply by a vector___Zhaohui__07-07-1999                     
00868 // vector arg(i), i from 1 to neq, but return[i], i from 0 to neq-1!!!!
00869 // bug found in July 27,99__Zhaohui
00870  double * profilematrix::operator*( BJvector & arg)
00871   {
00872     int irow, iau, colht, jp, neq;
00873     neq = this->pc_profilematrix_rep->neq;
00874 
00875     if( neq != arg.rows())
00876       error("# rows of second mat must equal "
00877                "# cols of first for multiply#");
00878     double  *result;
00879     result = new double [ neq];
00880     if (! result)
00881         {
00882           ::printf("\a\nInsufficient memory for result\n");
00883           ::exit(1);
00884         }
00885     // initializing result!
00886     for (int init=0; init<neq; init++)
00887        result[init] = 0.0;
00888 
00889 //    this->profile_al_print();
00890 //    for( int i=0 ; i<neq ; i++ )
00891 //       ::printf(" \n jp=%d",this->pc_profilematrix_rep->jp[i] );
00892 
00893     for( int i=0 ; i<neq ; i++ )
00894      {
00895       result[i] += this->pc_profilematrix_rep->ad[i] * arg.val(i+1);
00896 //       ::printf(" \n\nI%d %+6.2e%+6.2e%+6.2e\n\n",i,this->pc_profilematrix_rep->ad[i],arg.val(i+1),result[i+1] );
00897       jp = this->pc_profilematrix_rep->jp[i];
00898       if ( i==0 )
00899          {
00900           colht = 0;
00901          }
00902         else
00903          {
00904           colht = this->pc_profilematrix_rep->jp[i]-this->pc_profilematrix_rep->jp[i-1];
00905          }
00906 
00907       for( int j=1 ; j<=colht ; j++ )
00908        {
00909           // remember that au[i], i starts from 0!!!
00910           //iau = jp - j +1;
00911           iau = jp - j ;
00912           irow = i  -j ;
00913           result[irow] +=this->pc_profilematrix_rep->au[iau] * arg.val(i+1);
00914           result[i]  +=this->pc_profilematrix_rep->al[iau] * arg.val(irow+1);
00915 //       ::printf(" \n\nJ%d %+6.2e%+6.2e%+6.2e\n\n",j,this->pc_profilematrix_rep->au[iau],arg.val(i+1),result[irow] );
00916        }
00917      
00918 //      ::printf(" \n\n  %+6.2e\n", result[i+1] );
00919       
00920      }
00921 //   for( int i=0 ; i<neq ; i++ )
00922 //       ::printf(" \n result=%+6.2e arg=%+6.2e\n", result[i+1], arg.val(i+1) );
00923   return result;
00924   }
00925 
00926 
00927 //..//##############################################################################
00928 // scalar multiplication
00929 profilematrix  profilematrix::operator*( double rval)
00930  {
00931 // construct profilematrix using the same control numbers as for the
00932 // original one.
00933     profilematrix mult(this->pc_profilematrix_rep->neq,
00934                        this->pc_profilematrix_rep->jp,
00935                        this->pc_profilematrix_rep->flag,
00936                        this->pc_profilematrix_rep->al,
00937                        this->pc_profilematrix_rep->au,
00938                        this->pc_profilematrix_rep->ad);
00939 
00940   for (int kau=0 ; kau<pc_profilematrix_rep->total_numb ; kau++)
00941      mult.pc_profilematrix_rep->au[kau] *= rval;
00942    for (int kad=0 ; kad<this->pc_profilematrix_rep->neq ; kad++)
00943      mult.pc_profilematrix_rep->ad[kad] *= rval;
00944   if ( this->pc_profilematrix_rep->flag == 'N' )
00945     {
00946       for ( int kal=0 ; kal<this->pc_profilematrix_rep->total_numb ; kal++ )
00947        mult.pc_profilematrix_rep->al[kal] *= rval;
00948     }
00949 //    for (int kau=0 ; kau<this->pc_profilematrix_rep->total_numb ; kau++)
00950 //      this->pc_profilematrix_rep->au[kau] *= rval;
00951 //    for (int kad=0 ; kad<this->pc_profilematrix_rep->neq ; kad++)
00952 //      this->pc_profilematrix_rep->ad[kad] *= rval;
00953 //    if ( this->pc_profilematrix_rep->flag == 'N' )
00954 //      {
00955 //        for ( int kal=0 ; kal<this->pc_profilematrix_rep->total_numb ; kal++ )
00956 //         this->pc_profilematrix_rep->al[kal] *= rval;
00957 //      }
00958 //..// This is OK
00959 //..    else if ( this->pc_profilematrix_rep->flag == 'S' )
00960 //..      {
00961 //..        this->pc_profilematrix_rep->al = New_pc_profilematrix_rep->au;
00962 //..      }
00963 //..    else
00964 //..      {
00965 //..        ::printf("flags not set properly, flag=='S' symmetric; flag=='N' NON(un)symmetric\n");
00966 //..      }
00967 
00968     return  mult;
00969  }
00970 
00971 
00972 
00973 // only for the members inside
00974 // the profile !!!!!!!!!!!
00975 // so row and col must be within profile !!!!!!!!!!!!!!!
00976 //##########################################################################
00977 // this one is the same as mval except that it is more convinient  //  ________
00978 // to overload operator (row,col).                                 // |  rows
00979 double & profilematrix::operator( )(int row, int col) const        // |c
00980   {                                                                // |o
00981     if( row==col )                                                 // |l
00982       {                                                            // |u
00983         return this->pc_profilematrix_rep->ad[row-1];              // |m
00984       }                                                            // |n
00985     else if( row<col ) // upper part AU                                 // |s
00986       {
00987         int  next_to_diag_memb = *(this->pc_profilematrix_rep->jp+col-1);//-1:starts from 0
00988         int member_of_profile_n = next_to_diag_memb - (col-1) + row;
00989         double *member_of_profile = &(pc_profilematrix_rep->au[member_of_profile_n-1]);//-1:starts from 0
00990         return (*member_of_profile);
00991       }
00992     else // if( col<row ) // lower part AL
00993       {
00994         int  next_to_diag_memb = *(this->pc_profilematrix_rep->jp+row-1);//-1:starts from 0
00995         int member_of_profile_n = next_to_diag_memb - (row-1) + col;
00996         double *member_of_profile = &(pc_profilematrix_rep->al[member_of_profile_n-1]);//-1:starts from 0
00997         return (*member_of_profile);
00998       }
00999 //..    else
01000 //..      {
01001 //..        double zero=0.0;
01002 //..        return zero;
01003 //..      }
01004   }
01005 
01006 //##########################################################################
01007 double & profilematrix::mval(int row, int col) const // only for the members inside
01008   {                                                  // the profile !!!!!!!!!!!
01009     if( row==col )                                   // so row and col must be
01010       {                                              // within profile !!!!!!!!!!!!!!!
01011         return this->pc_profilematrix_rep->ad[row-1];
01012       }
01013     else if( row<col ) // upper part AU
01014       {
01015         int  next_to_diag_memb = *(this->pc_profilematrix_rep->jp+col-1);//-1:starts from 0
01016         int member_of_profile_n = next_to_diag_memb - (col-1) + row;
01017         double *member_of_profile = &(pc_profilematrix_rep->au[member_of_profile_n-1]);//-1:starts from 0
01018         return (*member_of_profile);
01019       }
01020     else //if( col<row ) // lower part AL
01021       {
01022         int  next_to_diag_memb = *(this->pc_profilematrix_rep->jp+row-1);//-1:starts from 0
01023         int member_of_profile_n = next_to_diag_memb - (row-1) + col;
01024         double *member_of_profile = &(pc_profilematrix_rep->al[member_of_profile_n-1]);//-1:starts from 0
01025         return (*member_of_profile);
01026       }
01027 //..    else
01028 //..      {
01029 //..        double zero=0.0;
01030 //..        return zero;
01031 //..      }
01032   }
01033 
01034 
01035 
01036 //##########################################################################
01037 // full_val function allows you to treat profilematrix as if it is full
01038 // float matrix. The function will calculate position inside profile matrix
01039 // and return appropriate number if row and col are bellow/right profile line or
01040 // return zero (0) if row and col are above/left profile line
01041 double profilematrix::full_val(int row, int col) const
01042   {
01043     if( row==col )
01044       {
01045         return this->pc_profilematrix_rep->ad[row-1];
01046       }
01047     else if( row<col ) // upper part AU
01048       {
01049         int total_column_depth = col-1;
01050         int actual_column_position = row;  // - total_column_depth + 2;
01051         int real_column_depth = pc_profilematrix_rep->jp[col-1] -
01052                                  pc_profilematrix_rep->jp[col-1-1];
01053         int zeros_above_profile =
01054           total_column_depth-real_column_depth;
01055         int how_much_above_profile =
01056           zeros_above_profile-actual_column_position+1;
01057         if ( how_much_above_profile > 0 )
01058           {
01059             double back = 0.0;    
01060             return ( back );
01061           }
01062         else
01063           {
01064             int  next_to_diag_memb =
01065               *(this->pc_profilematrix_rep->jp+col-1);//-1:starts from 0
01066             int member_of_profile_n =
01067               next_to_diag_memb - total_column_depth + row - 1;
01068             double *member_of_profile =
01069               &(pc_profilematrix_rep->au[member_of_profile_n]);
01070             return (*member_of_profile);
01071           }
01072       }
01073     else if( col<row ) // lower part AL
01074       {
01075         int total_row_width = row-1;
01076         int actual_row_position = col;  // - total_row_width + 2;
01077         int real_row_width = pc_profilematrix_rep->jp[row-1] -
01078                              pc_profilematrix_rep->jp[row-1-1];
01079         int zeros_left_of_profile =
01080           total_row_width-real_row_width;
01081         int how_much_left_of_profile =
01082           zeros_left_of_profile-actual_row_position+1;
01083         if ( how_much_left_of_profile > 0 )
01084           {
01085             double back = 0.0;    
01086             return ( back );
01087           }
01088         else
01089           {
01090             int  next_to_diag_memb =
01091               *(this->pc_profilematrix_rep->jp+row-1);//-1:starts from 0
01092             int member_of_profile_n =
01093               next_to_diag_memb - total_row_width + col - 1;
01094             double *member_of_profile =
01095               &(pc_profilematrix_rep->al[member_of_profile_n]);
01096             return (*member_of_profile);
01097           }
01098       }
01099     else return 0.0;
01100   }
01101      // used by profmatrix functions which KNOW they aren't
01102      // exceeding the boundaries
01103 
01104 
01105 //##########################################################################
01106 double & profilematrix::val(int row, int col)
01107   {
01108 //    double zero=0.0;
01109     if ( row<=0 && row>=dimension_of_profile_M() && col>=dimension_of_profile_M() )
01110       {
01111         error("index out of range");
01112 //        return zero;
01113       }
01114 //    else
01115       return (mval(row,col));
01116   }
01117 
01118 //##########################################################################
01119 double profilematrix::cval(int row, int col) const
01120   {
01121     double zero=0.0;
01122     if ( row<=0 && row>=dimension_of_profile_M() && col>=dimension_of_profile_M() )
01123       {
01124         error("index out of range");
01125         return zero;
01126       }
01127 //    else
01128       return (mval(row,col));
01129   }
01130 
01131 
01132 //##########################################################################
01133 double profilematrix::mmin()
01134   {
01135     double temp;
01136     if ( dimension_of_profile_M()<=0 )
01137       error("bad profilematrix size for min ()");
01138     double minimum = full_val(1,1);
01139     for ( int row=1 ; row<=dimension_of_profile_M() ; row++ )
01140       for ( int col=1 ; col<=dimension_of_profile_M() ; col++ )
01141         if ( (temp=full_val(row,col)) < minimum )
01142           minimum = temp;
01143     return minimum;
01144   }
01145 
01146 //##########################################################################
01147 double profilematrix::mmax()
01148   {
01149     double temp=0.0;
01150     if( dimension_of_profile_M()<=0 )
01151       error("bad profilematrix size for max()");
01152     double maximum = full_val(1,1);
01153     for ( int row=1 ; row<=dimension_of_profile_M() ; row++ )
01154       for ( int col=1 ; col<=dimension_of_profile_M() ; col++ )
01155         {
01156           if ( (temp=full_val(row,col)) > maximum )
01157           maximum = temp;
01158         }
01159     return maximum;
01160   }
01161 
01162 //##########################################################################
01163 double profilematrix::mean()
01164   {
01165     int col = 0;
01166     int row = 1; 
01167     double sum = 0;
01168     for ( row=1 ; row<=dimension_of_profile_M() ; row++ )
01169       for ( col=1 ; col<=dimension_of_profile_M() ; col++ )
01170         sum += fabs(full_val(row,col));
01171     return sum/(row*col);
01172   }
01173 
01174 
01175 //..//##########################################################################
01176 //..void profilematrix::lower_print(char *msg)
01177 //..  {
01178 //..    if (*msg) printf("%s\n",msg);
01179 //..    for ( int row=1 ; row<=dimension_of_prof_M() ; row++ )
01180 //..      {
01181 //..        int total_column_height = row;
01182 //..        int real_column_height = pc_profilematrix_rep->p_maxa[row] - pc_profilematrix_rep->p_maxa[row-1];
01183 //..        int numb_of_voids = total_column_height - real_column_height;
01184 //..        int n_of_voids_to_reach_number = numb_of_voids;
01185 //..        for ( int col=1 ; col<=row ; col++ )
01186 //..          {
01187 //..            if( n_of_voids_to_reach_number > 0 )
01188 //..              {
01189 //..                 for(int void_count=1; void_count<=numb_of_voids; void_count++)
01190 //..                  {
01191 //..                    printf("   **   ");
01192 //..                    col++;
01193 //..                    n_of_voids_to_reach_number--;
01194 //..                  }
01195 //..              }
01196 //..            printf( "%7.4f ", mval(row,col) );
01197 //..          }
01198 //..        printf("\n");
01199 //..      }
01200 //..  }
01201 //..
01202 //..//##########################################################################
01203 //..void profilematrix::upper_print(char *msg)
01204 //..  {
01205 //..    if (*msg) printf("%s\n",msg);
01206 //..    for ( int row=1 ; row<=dimension_of_prof_M() ; row++ )
01207 //..      {
01208 //..        for ( int voids=0 ; voids<row-1 ; voids++ ) printf("        ");
01209 //..        for ( int col=row ; col<=dimension_of_prof_M() ; col++ )
01210 //..          {
01211 //..            int total_column_height = col;
01212 //..            int actual_column_position = total_column_height - row + 1;
01213 //..            int real_column_height = pc_profilematrix_rep->p_maxa[col] - pc_profilematrix_rep->p_maxa[col-1];
01214 //..            int how_much_above_profline=actual_column_position-real_column_height;
01215 //..            if ( how_much_above_profline > 0 )
01216 //..              {
01217 //..                printf("   **   ");
01218 //..              }
01219 //..            else
01220 //..              {
01221 //..                printf( "%7.4f ", mval(col,row) );
01222 //..              }
01223 //..          }
01224 //..        printf("\n");
01225 //..      }
01226 //..  }
01227 
01228 
01229 //tempout////#############################################################################
01230 //tempout// Assemble global stiffness matrix from local contributions 
01231 //tempout// and store it in porfile format!_____Zhaohui 06-30-99
01232 //tempoutprofilematrix & profilematrix::AssembleBricksInProfMatrix(stiffness_matrix & Ke,
01233 //tempout                                                          Brick3D          * b3d,
01234 //tempout                                                          Node             * node,
01235 //tempout                                                         FEModelData      & FEMD,
01236 //tempout                                                          float              scale // used to add damping matrix C to Kbar Zhaohui 
01237 //tempout                                                                                )
01238 //tempout  {
01239 //tempout
01240 //tempout//    ::printf("\n\n");
01241 //tempout
01242 //tempout    int *lm = b3d->get_LM();
01243 //tempout
01244 //tempout
01245 //tempout// KJBathe pp1003 ADDBAN
01246 //tempout
01247 //tempout    int DOF_count_for_Brick = 24;
01248 //tempout    int II = 0;
01249 //tempout    int MI = 0;
01250 //tempout    int MJ = 0;
01251 //tempout    int JJ = 0;
01252 //tempout    int IJ = 0;
01253 //tempout    int KK = 0;
01254 //tempout
01255 //tempout//    int Numb_of_DOF = FEMD.get_number_of_DOFs(); 
01256 //tempout//    int length_of_AL = pc_profilematrix_rep->jp[Numb_of_DOF-1];
01257 //tempout//
01258 //tempout//// allocate memory for the actual profilematrix as profilematrix
01259 //tempout//    pc_profilematrix_rep->al = new double [(size_t) length_of_AL];
01260 //tempout//      if (!pc_profilematrix_rep->al)
01261 //tempout//        { printf("\a\nInsufficient memory for AL\n"); exit(1);}
01262 //tempout//    pc_profilematrix_rep->ad = new double [(size_t) Numb_of_DOF];
01263 //tempout//      if (!pc_profilematrix_rep->ad)
01264 //tempout//        { printf("\a\nInsufficient memory for AD\n"); exit(1);}
01265 //tempout//    pc_profilematrix_rep->au = new double [(size_t) length_of_AL];
01266 //tempout//      if (!pc_profilematrix_rep->au)
01267 //tempout//        { printf("\a\nInsufficient memory for AU\n"); exit(1);}
01268 //tempout//
01269 //tempout//    for (int I = 0 ; I < length_of_AL ; I++)   // Initialization.
01270 //tempout//      {
01271 //tempout//      pc_profilematrix_rep->al[I] = 0.0;
01272 //tempout//      pc_profilematrix_rep->au[I] = 0.0;
01273 //tempout//       }
01274 //tempout//    for (int I = 0 ; I < Numb_of_DOF ; I++)   // Initialization.
01275 //tempout//      {
01276 //tempout//      pc_profilematrix_rep->ad[I] = 0.0;
01277 //tempout//       }
01278 //tempout//  THIS PART HAS BEEN MOVED OUTSIDE AND BECOME INDEPENDENT SUBROUTINE!!
01279 //tempout
01280 //tempout    for (int I = 1 ; I <= DOF_count_for_Brick ; I++)
01281 //tempout      {
01282 //tempout        II =  lm[I-1];
01283 //tempout        if (II > 0) 
01284 //tempout          {
01285 //tempout            MI = pc_profilematrix_rep->jp[II - 1];  
01286 //tempout            for (int J = 1 ; J <= DOF_count_for_Brick ; J++)
01287 //tempout              {
01288 //tempout                JJ = lm[J-1];
01289 //tempout                if (JJ > 0)
01290 //tempout                  {
01291 //tempout                    MJ = pc_profilematrix_rep->jp[JJ - 1];//new variable corresponding to MI
01292 //tempout                    IJ = II - JJ;
01293 //tempout                    
01294 //tempout                   if (IJ > 0 ) // Lower triangular!
01295 //tempout                      { 
01296 //tempout                        KK = MI - IJ + 1;
01297 //tempout                        pc_profilematrix_rep->al[KK-1] = 
01298 //tempout                         pc_profilematrix_rep->al[KK-1] + Ke.val(I,J)*scale;
01299 //tempout                      }
01300 //tempout                    
01301 //tempout                   else if (IJ == 0 ) // Diagonal elements
01302 //tempout                      { 
01303 //tempout                        KK = II ;
01304 //tempout                        pc_profilematrix_rep->ad[KK-1] = 
01305 //tempout                         pc_profilematrix_rep->ad[KK-1] + Ke.val(I,J)*scale;
01306 //tempout                      }
01307 //tempout                    
01308 //tempout                   else if (IJ < 0 )  // Upper triangular!
01309 //tempout                      { 
01310 //tempout                        KK = MJ + IJ + 1;
01311 //tempout                        pc_profilematrix_rep->au[KK-1] = 
01312 //tempout                         pc_profilematrix_rep->au[KK-1] + Ke.val(I,J)*scale;
01313 //tempout                      }
01314 //tempout
01315 //tempout                  }
01316 //tempout
01317 //tempout              }
01318 //tempout
01319 //tempout          }
01320 //tempout      }
01321 //tempout  
01322 //tempout
01323 //tempout//// Print AL, AD, AU for chencking purpose.
01324 //tempout//    ::printf("\n\nAD= ");
01325 //tempout//      for (int count05 = 0 ; count05 < Numb_of_DOF ; count05++)
01326 //tempout//      {
01327 //tempout//       ::printf("  ad %6.2e ",  pc_profilematrix_rep->ad[count05] );
01328 //tempout////       ::printf("  assem jp %d \n",  pc_profilematrix_rep->jp[count05] );
01329 //tempout// }
01330 //tempout//
01331 //tempout//       ::printf(" \n\n AL= ");
01332 //tempout//      for (int count05 = 0 ; count05 < length_of_AL ; count05++)
01333 //tempout//      {
01334 //tempout//       ::printf(" %6.2e ",  pc_profilematrix_rep->al[count05] );
01335 //tempout//      }
01336 //tempout//       ::printf(" \n\nAU= ");
01337 //tempout//      for (int count05 = 0 ; count05 < length_of_AL ; count05++)
01338 //tempout//      {
01339 //tempout//       ::printf(" %6.2e ",  pc_profilematrix_rep->au[count05] );
01340 //tempout//      }
01341 //tempout//
01342 //tempout//      ::printf("\n\n=============\n\n");
01343 //tempout//
01344 //tempout//
01345 //tempout    return * this;
01346 //tempout }
01347 //tempout
01348 
01349 //##########################################################################
01350 // print jp of profilematrix
01351 void profilematrix::profile_jp_print( void )
01352  {
01353    ::printf("\n jp \n\n " );
01354    for (int count05 = 0 ; count05 < pc_profilematrix_rep->neq ; count05++)
01355       ::printf("  jp %d ",  pc_profilematrix_rep->jp[count05] );
01356  }
01357 
01358 //##########################################################################
01359 //##########################################################################
01360 // print pc_profilematrix_rep->au--Zhaohui
01361 void profilematrix::profile_al_print( void )
01362 { ::printf("\n al \n\n " );
01363  for (int count05 = 0 ; count05 <pc_profilematrix_rep->jp[pc_profilematrix_rep->neq-1] ; count05++)
01364       {
01365        ::printf(" al %10.3e ",  pc_profilematrix_rep->al[count05] );
01366       }
01367 }
01368 
01369 //##########################################################################
01370 // print pc_profilematrix_rep->ad--Zhaohui
01371 void profilematrix::profile_ad_print( void )
01372 { ::printf("\n al \n\n " );
01373  for (int count05 = 0 ; count05 <pc_profilematrix_rep->neq ; count05++)
01374       {
01375        ::printf(" ad %10.3e\n ",  pc_profilematrix_rep->ad[count05] );
01376       }
01377 }
01378 
01379 //##########################################################################
01380 void profilematrix::full_print(char *msg)
01381   {
01382     if (*msg) printf("%s\n",msg);
01383     for ( int row=1 ; row<=dimension_of_profile_M() ; row++ )
01384       {
01385         for ( int col=1 ; col<=dimension_of_profile_M() ; col++ )
01386           {
01387             printf( "%+8.3e ", full_val(row,col) );
01388           }
01389         printf("\n");
01390       }
01391   }
01392 
01393 
01394 //##########################################################################
01395 void profilematrix::error(char * msg1, char * msg2) const
01396   {
01397     ::fprintf(stderr,"profmatrix error: %s %s\n", msg1, msg2);
01398     exit( 1 );
01399   }
01400 
01401 
01402 
01403 
01405 
01406 
01407 //##############################################################################
01408 // very private part
01409 //##############################################################################
01410 //..   double * profilematrix::data(void) const
01411 //..    {
01412 //..      return this->pc_profilematrix_rep->pd_nDdata;
01413 //..    }
01414 //..
01415 //..    void profilematrix::set_data_pointer(double * data_pointer)
01416 //..    {
01417 //..      this->pc_profilematrix_rep->pd_nDdata = data_pointer;
01418 //..    }
01419 //
01420 //    int profilematrix::rank(void) const
01421 //    {
01422 //      return this->pc_profilematrix_rep->profilematrix_rank;
01423 //    }
01424 
01425 //    void profilematrix::rank(int profilematrix_rank)
01426 //    {
01427 //      this->pc_profilematrix_rep->profilematrix_rank = profilematrix_rank;
01428 //    }
01429 //
01430     long int profilematrix::total_number(void) const
01431     {
01432       return this->pc_profilematrix_rep->total_numb;
01433     }
01434 
01435     void profilematrix::total_number(int number)
01436     {
01437       this->pc_profilematrix_rep->total_numb = number;
01438     }
01439 
01440 //    int * profilematrix::dim(void) const
01441 //    {
01442 //      return this->pc_profilematrix_rep->dim;
01443 //    }
01444 //
01445 //    int & profilematrix::get_dim_pointer(void) const
01446 //    {
01447 //      return this->pc_profilematrix_rep->dim[0];
01448 //    }
01449 //
01450 //    void profilematrix::set_dim_pointer(int * dim_pointer)
01451 //    {
01452 //      this->pc_profilematrix_rep->dim = dim_pointer;
01453 //    }
01454 //
01455 //    int profilematrix::dim(int which) const
01456 //    {
01457 //      return this->pc_profilematrix_rep->dim[which-1];
01458 //    }
01459 //
01460     int profilematrix::reference_count(int up_down)
01461     {
01462       this->pc_profilematrix_rep->n += up_down;
01463       return(this->pc_profilematrix_rep->n);
01464     }
01465 
01466     void profilematrix::set_reference_count(int ref_count)
01467     {
01468       this->pc_profilematrix_rep->n=ref_count;
01469     }
01470 
01471 
01472 //##############################################################################
01473 // TENSOR_REP_CC
01474 // #######################
01475 // memory manager part
01476 // overloading operator new in profilematrix::profilematrix_rep class  ##################
01477 void * profilematrix_rep::operator new(size_t s)
01478   {                                       // see C++ reference manual by
01479     void *void_pointer;                   // ELLIS and STROUSTRUP page 283.
01480     void_pointer = ::operator new(s);     // and ECKEL page 529.
01481 //    ::printf("\nnew pointer %p of size %d\n",void_pointer,s);
01482     if (!void_pointer)
01483       {
01484         ::printf("\a\nInsufficient memory\n");
01485         ::exit(1);
01486       }
01487     return void_pointer;
01488   }
01489 
01490 // overloading operator delete in profilematrix::profilematrix_rep class  ##################
01491 void profilematrix_rep::operator delete(void *p)
01492   {                                       // see C++ reference manual by
01493                                           // ELLIS and STROUSTRUP page 283.
01494                                           // and ECKEL page 529.
01495 //    ::printf("deleted pointer %p\n",p);
01496     ::operator delete(p);
01497   }
01498 
01499 
01500 
01501 //##############################################################################
01502 //##############################################################################
01503 // DATRI triangularization of profile matrix stored in profile form.
01504 // Both symmetric and unsymmetric profile matrices can be solved!!
01505 // this is important for the nonassociated flow theories in plasticity!
01506 // FORTRAN source code taken from the chapter 15 of FEM IV ed. by
01507 // O. C. Zienkiewicz and R. L. Taylor. See also " Solution of linear
01508 // equations by a profile solver" in Eng. Comp. 1985 Vol 2
01509 // December pages: 344-350.
01510 profilematrix & profilematrix::datri(void)
01511   {
01512 //  c
01513 //        subroutine datri(al,au,ad,jp,neq,flg)
01514 //        implicit real*8 (a-h,o-z)
01515 //  c.... triangular decomposition of a matrix stored in profile form
01516 //        logical flg
01517 //        integer*2 jp(1)
01518 //        real*8 al(1),au(1),ad(1)
01519 //        common /iofile/ ior,iow
01520 //  c.... n.b.  tol should be set to approximate half-word precision.
01521 //        data zero,one/0.0d0,1.0d0/, tol/0.5d-07/
01522     double zero = 0.0;
01523     double one  = 1.0;
01524     double tol  = sqrt(d_macheps());
01525 //  c.... set initial values for conditioning check
01526 //        dimx = zero
01527 //        dimn = zero
01528     double dimx = zero;
01529     double dimn = zero;
01530 //        do 50 j = 1,neq
01531 //        dimn = max(dimn,abs(ad(j)))
01532 //  50    continue
01533     int j = 1;
01534     for ( j=1 ; j<=pc_profilematrix_rep->neq ; j++ )
01535 //      dimn = max(dimn,(fabs(pc_profilematrix_rep->ad[j-1])));
01536 //..      dimn =
01537      if ( dimn < fabs(pc_profilematrix_rep->ad[j-1]) )
01538         dimn = fabs(pc_profilematrix_rep->ad[j-1]);
01539 //        dfig = zero
01540     double dfig = zero;
01541 //  c.... loop through the columns to perform the triangular decomposition
01542 //        jd = 1
01543     int jd = 1;
01544 //        do 200 j = 1,neq
01545 
01546     int jr = 0;
01547     int jh = 0;
01548     int is = 0;
01549     int ie = 0;
01550     int id = 0;
01551     int ih = 0;
01552     int jrh = 0;
01553     int idh = 0;
01554     double dd    = 0;
01555 //    double dj    = 0;
01556 //    double ud    = 0;
01557     double ifig  = 0;
01558     double daval = 0.0;
01559 
01560 
01561     for ( j=1 ; j<=pc_profilematrix_rep->neq ; j++ )
01562       {
01563 //          jr = jd + 1
01564         jr = jd + 1;
01565 //          jd = jp(j)
01566         jd = pc_profilematrix_rep->jp[j-1];
01567 //          jh = jd - jr
01568         jh = jd -jr;
01569 //          if(jh.gt.0) then
01570         if ( jh > 0 )
01571           {
01572 //            is = j - jh
01573             is = j - jh;
01574 //            ie = j - 1
01575             ie = j - 1;
01576 //  c.... if diagonal is zero compute a norm for singularity test
01577 //            if(ad(j).eq.zero) call Ndatest(au(jr),jh,daval)
01578             if ( pc_profilematrix_rep->ad[j-1] == zero )
01579               daval = datest((pc_profilematrix_rep->ad+jr-1), jh);
01580 //            do 100 i = is,ie
01581             for ( int i=is ; i<=ie ; i++ )
01582               {
01583 //              jr = jr + 1
01584                 jr = jr + 1;
01585 //              id = jp(i)
01586                 id = pc_profilematrix_rep->jp[i-1];
01587 //              ih = min(id-jp(i-1),i-is+1)
01588 //                ih = min((id-pc_profilematrix_rep->jp[i-1-1]),(i-is+1));
01589                 ih = id - pc_profilematrix_rep->jp[i-1-1]; // ____Zhaohui
01590                 if (ih >(i-is+1))  ih = i-is+1;          // ____Zhaohui
01591 
01592                 if ( ih > 0 )
01593                   {
01594 //                jrh = jr - ih
01595                     jrh = jr - ih;
01596 //                idh = id - ih + 1
01597                     idh = id -ih + 1;
01598 //                au(jr) = au(jr) - dot(au(jrh),al(idh),ih)
01599                     pc_profilematrix_rep->au[jr-1] =
01600                       pc_profilematrix_rep->au[jr-1] -
01601                       dot((pc_profilematrix_rep->au+jrh-1),
01602                           (pc_profilematrix_rep->al+idh-1), ih);
01603 //                if(flg) al(jr) = al(jr) - dot(al(jrh),au(idh),ih)
01604                     if ( pc_profilematrix_rep->flag == 'N' )
01605                     pc_profilematrix_rep->al[jr-1] =
01606                       pc_profilematrix_rep->al[jr-1] -
01607                       dot((pc_profilematrix_rep->al+jrh-1),
01608                           (pc_profilematrix_rep->au+idh-1), ih);
01609 //              endif
01610                   }
01611 
01612 //  100       continue
01613               }
01614 //          endif
01615           }
01616 //  c.... reduce the diagonal
01617 //          if(jh.ge.0) then
01618         if ( jh >= 0 )
01619           {
01620 //            dd = ad(j)
01621             dd = pc_profilematrix_rep->ad[j-1];
01622 //            jr = jd - jh
01623             jr = jd - jh;
01624 //            jrh = j - jh - 1
01625             jrh = j - jh - 1;
01626 //            call dredu(al(jr),au(jr),ad(jrh),jh+1,flg  ,ad(j))
01627             dredu((pc_profilematrix_rep->al+jr-1),
01628                   (pc_profilematrix_rep->au+jr-1),
01629                   (pc_profilematrix_rep->ad+jrh-1),
01630                   (jh+1),
01631                   (pc_profilematrix_rep->flag),
01632                   (pc_profilematrix_rep->ad+j-1) );
01633 //  c.... check for possible errors and print warnings
01634 //            if(abs(ad(j)).lt.tol*abs(dd))  write(iow,2000) j
01635             if ( (fabs(pc_profilematrix_rep->ad[j-1])<(tol*fabs(dd))) )
01636 ::printf("***DATRI WARNING 1***\n Loss of at least N digits in reducing diagonal of equation %d\n",j);
01637 //            if(dd.lt.zero.and.ad(j).gt.zero) write(iow,2001) j
01638             if ( (dd<zero) && (pc_profilematrix_rep->ad[j-1]>zero) )
01639 ::printf("***DATRI WARNING 2***\n Sign of diagonal changed when reducing equation %d\n",j);
01640 //            if(dd.gt.zero.and.ad(j).lt.zero) write(iow,2001) j
01641             if ( (dd>zero) && (pc_profilematrix_rep->ad[j-1]<zero) )
01642 ::printf("***DATRI WARNING 2***\n Sign of diagonal changed when reducing equation %d\n",j);
01643 //            if(ad(j) .eq.  zero)             write(iow,2002) j
01644             if ( (pc_profilematrix_rep->ad[j-1]==zero) ) // strange it is never == 0 but macheps!!!!!!!!!!!!
01645 ::printf("***DATRI WARNING 3***\n Reduced diagonal is zero for equation %d\n",j);
01646 //            if(dd.eq.zero.and.jh.gt.0) then
01647             if ( (dd==zero) && (jh>0) ) // strange it is never == 0 but macheps!!!!!!!!!!!!
01648 //              if(abs(ad(j)).lt.tol*daval)   write(iow,2003) j
01649               if ( (fabs(pc_profilematrix_rep->ad[j-1])<(tol*daval)) )
01650 ::printf("***DATRI WARNING 4***\n Rank failure for zero unreduced diagonal in equation %d\n",j);
01651 //            endif
01652 //          endif
01653           }
01654 //  c.... store reciprocal of diagonal, compute condition checks
01655 //          if(ad(j).ne.zero) then
01656         if ( pc_profilematrix_rep->ad[j-1] != zero )
01657           {
01658 //            dimx  = max(dimx,abs(ad(j)))
01659 //            dimx = max(dimx,fabs(pc_profilematrix_rep->ad[j-1]));
01660               if (dimx < fabs(pc_profilematrix_rep->ad[j-1])) 
01661                  dimx = fabs(pc_profilematrix_rep->ad[j-1]);
01662 //            dimn  = min(dimn,abs(ad(j)))
01663 //            dimn = min(dimn,fabs(pc_profilematrix_rep->ad[j-1]));
01664               if (dimn > fabs(pc_profilematrix_rep->ad[j-1])) 
01665                  dimn = fabs(pc_profilematrix_rep->ad[j-1]);
01666 //            dfig  = max(dfig,abs(dd/ad(j)))
01667 //            dfig = max(dfig,fabs(dd/pc_profilematrix_rep->ad[j-1]));
01668               if (dfig <fabs(dd/pc_profilematrix_rep->ad[j-1])) 
01669                  dfig=fabs(dd/pc_profilematrix_rep->ad[j-1]); 
01670 //            ad(j) = one/ad(j)
01671             pc_profilematrix_rep->ad[j-1] = one/pc_profilematrix_rep->ad[j-1];
01672 //          endif
01673           }
01674 //  200   continue
01675       }
01676 //  c.... print conditioning information
01677 //        dd = zero
01678     dd = zero;
01679 //        if(dimn.ne.zero) dd = dimx/dimn
01680     if ( dimn != zero ) dd = dimx/dimn;
01681 //        ifig = dlog10(dfig) + 0.6
01682     ifig = log (dfig) + 0.6;
01683 //        write(iow,2004) dimx,dimn,dd,ifig
01684     ::printf("\n-------- Condition check:\n D-max %f\n D-min %f\n Ratio %f\n Maximum no. diagonal digits lost: %f\n",
01685               dimx , dimn, dd, ifig);
01686 //        if(ior.lt.0) write(*,2004) dimx,dimn,dd,ifig
01687 //        return
01688 //        end
01689 //
01690 
01691     return *this;
01692   }
01693 
01694 
01695 
01696 //##############################################################################
01697 //##############################################################################
01698 // DASOL solution of the equations after triangular decomposition
01699 // Both symmetric and unsymmetric profile matrices can be solved!!
01700 // this is important for the nonassociated flow theories in plasticity!
01701 // FORTRAN source code taken from the chapter 15 of FEM IV ed. by
01702 // O. C. Zienkiewicz and R. L. Taylor. See also " Solution of linear
01703 // equations by a profile solver" in Eng. Comp. 1985 Vol 2
01704 // December pages: 344-350.
01705 double * profilematrix::dasol(double * b)
01706   {
01707 //c
01708 //      subroutine dasol(al,au,ad,b,jp,neq, energy)
01709 //      implicit real*8 (a-h,o-z)
01710 //c.... solution of symmetric equations stored in profile form
01711 //c.... coefficient matrix must be decomposed into its triangular
01712 //c.... factors using datri before using dasol.
01713 //      integer*2 jp(1)
01714 //      real*8 al(1),au(1),ad(1),b(1)
01715 //      common /iofile/ ior,iow
01716 //      data zero/0.0d0/
01717     double zero = 0.0;
01718 //c.... find the first nonzero entry in the right hand side
01719 //      do 100 is = 1,neq
01720 //        if(b(is).ne.zero) go to 200
01721 //100   continue
01722 
01723     int jr = 0;
01724     int jh = 0;
01725     double bd  = 0.0;
01726     int is = 1;
01727     for ( is=1 ; is<=pc_profilematrix_rep->neq ; is++ )
01728       {
01729         if ( b[is-1] != zero ) break;
01730       }
01731 //      write(iow,2000)
01732 //      if(ior.lt.0) write(*,2000)
01733     if ( is > pc_profilematrix_rep->neq )
01734       {
01735         ::printf("***DASOL WARNING 1***\n Zero right-hand-side vector\n");
01736         return b;
01737       }
01738 //      return
01739 //200   if(is.lt.neq) then
01740     if ( is < pc_profilematrix_rep->neq )
01741       {
01742 
01743 //c.... reduce the right hand side
01744 //        do 300 j = is+1,neq
01745         for ( int j=(is+1) ; j<=pc_profilematrix_rep->neq ; j++ )
01746           {
01747 //          jr = jp(j-1)
01748             jr = pc_profilematrix_rep->jp[j-1-1];
01749 //          jh = jp(j) - jr
01750             jh = pc_profilematrix_rep->jp[j-1] - jr;
01751 //          if(jh.gt.0) then
01752             if ( jh > 0 )
01753               {
01754 //            b(j) = b(j) - dot(al(jr+1),b(j-jh),jh)
01755                 b[j-1] = b[j-1] -
01756                          dot((pc_profilematrix_rep->al+jr+1-1),
01757                              (b+j-jh-1), jh);
01758               }
01759 //          endif
01760 //300     continue
01761           }
01762 //      endif
01763       }
01764 //c.... multiply by inverse of diagonal elements
01765 //      energy = zero
01766     double energy = zero;
01767 //      do 400 j = is,neq
01768     int j = is;
01769     for ( j=is ; j<=pc_profilematrix_rep->neq ; j++ )
01770       {
01771 //        bd = b(j)
01772         bd = b[j-1];
01773 //        b(j) = b(j)*ad(j)
01774         b[j-1] = b[j-1]*pc_profilematrix_rep->ad[j-1];
01775 //        energy = energy + bd*b(j)
01776         energy = energy + bd*b[j-1];
01777 //400   continue
01778       }
01779 //c.... backsubstitution
01780 //      if(neq.gt.1) then
01781     if ( pc_profilematrix_rep->neq > 1 )
01782       {
01783 //        do 500 j = neq,2,-1
01784         for ( j=pc_profilematrix_rep->neq ; j>=2 ; j-- )
01785           {
01786 //          jr = jp(j-1)
01787             jr = pc_profilematrix_rep->jp[j-1-1];
01788 //          jh = jp(j) - jr
01789             jh = pc_profilematrix_rep->jp[j-1] - jr;
01790 //          if(jh.gt.0) then
01791             if ( jh > 0 )
01792               {
01793 //            call saxpb(au(jr+1),b(j-jh),-b(j),jh, b(j-jh))
01794                 saxpb((pc_profilematrix_rep->au+jr+1-1),
01795                       (b+j-jh-1),
01796                       (-(b[j-1])),
01797                       jh,
01798                       (b+j-jh-1) );
01799 //          endif
01800               }
01801 //500     continue
01802           }
01803 //      endif
01804       }
01805 //      return
01806     return b;
01807 //      end
01808 
01809   }
01810 
01811 
01812 //      subroutine datest(au,jh,daval)
01813 //      implicit real*8 (a-h,o-z)
01814 //      real*8 au(jh)
01815 //c.... test for rank
01816 //      daval = 0.0d0
01817 //      do 100 j = 1,jh
01818 //         daval = daval + abs(au(j))
01819 //100   continue
01820 //      return
01821 //      end
01822 double profilematrix::datest(double* au, int jh)
01823   {
01824     double daval = 0.0;
01825     for ( int j=1 ; j<=jh ; j++ )
01826       daval += fabs(au[j-1]);
01827     return daval;
01828   }
01829 
01830 double profilematrix::dot(double* a, double* b, int n)
01831   {
01832     double dot = 0.0;
01833     for ( int i=1 ; i<=n ; i++ )
01834       dot += a[i-1]*b[i-1];
01835     return dot;
01836   }
01837 
01838 
01839 //..//            call dredu(al(jr),au(jr),ad(jrh),jh+1,flg  ,ad(j))
01840 //..      subroutine dredu(al,au,ad,jh,flg  ,dj)
01841 //..      implicit real*8 (a-h,o-z)
01842 //..c.... reduce diagonal element in triangular decomposition
01843 //..      logical flg
01844 //..      real*8 al(jh),au(jh),ad(jh)
01845 //..c.... computation of column for unsymmetric matrices
01846 //..      if(flg) then
01847 //..        do 100 j = 1,jh
01848 //..          au(j) = au(j)*ad(j)
01849 //..          dj    = dj - al(j)*au(j)
01850 //..          al(j) = al(j)*ad(j)
01851 //..100   continue
01852 //..c.... computation of column for symmetric matrices
01853 //..      else
01854 //..        do 200 j = 1,jh
01855 //..          ud    = au(j)*ad(j)
01856 //..          dj    = dj - au(j)*ud
01857 //..          au(j) = ud
01858 //..200     continue
01859 //..      endif
01860 //..      return
01861 //..      end
01862 void profilematrix::dredu(double* al,
01863                           double* au,
01864                           double* ad,
01865                           int jh,
01866                           char flag,
01867                           double* dj)
01868   {
01869     double ud = 0.0;
01870     if ( flag == 'N' )
01871       {
01872         for ( int j=1 ; j<=jh ; j++ )
01873           {
01874             au[j-1] = au[j-1]*ad[j-1];
01875             *dj = *dj - al[j-1]*au[j-1];
01876             al[j-1] = al[j-1]*ad[j-1];
01877           }
01878       }
01879     else
01880       {
01881         for ( int j=1 ; j<=jh ; j++ )
01882           {
01883             ud = au[j-1]*ad[j-1];
01884             *dj = *dj - au[j-1]*ud;
01885             au[j-1] = ud;
01886           }
01887       }
01888   }
01889 
01890 //            call saxpb(au(jr+1),b(j-jh),-b(j),jh, b(j-jh))
01891 //c                saxpb(a,       b,      x,     n, c      )
01892 //      subroutine saxpb (a,b,x,n,c)
01893 //      real*8 a(1),b(1),c(1),x
01894 //c... vector times scalar added to second vector
01895 //      do 10 k=1,n
01896 //        c(k) = a(k)*x +b(k)
01897 //   10 continue
01898 //      end
01899 void profilematrix::saxpb(double* a,
01900                           double* b,
01901                           double x,
01902                           int jh,
01903                           double* c)
01904   {
01905    for ( int k=1 ; k<=jh ; k++ )
01906      c[k-1] = a[k-1] * x + b[k-1];
01907   }
01908 
01909 
01910 #endif
01911 

Generated on Mon Oct 23 15:05:28 2006 for OpenSees by doxygen 1.5.0