|
OOFEM
2.1
|
00001 /* 00002 * 00003 * ##### ##### ###### ###### ### ### 00004 * ## ## ## ## ## ## ## ### ## 00005 * ## ## ## ## #### #### ## # ## 00006 * ## ## ## ## ## ## ## ## 00007 * ## ## ## ## ## ## ## ## 00008 * ##### ##### ## ###### ## ## 00009 * 00010 * 00011 * OOFEM : Object Oriented Finite Element Code 00012 * 00013 * Copyright (C) 1993 - 2013 Borek Patzak 00014 * 00015 * 00016 * 00017 * Czech Technical University, Faculty of Civil Engineering, 00018 * Department of Structural Mechanics, 166 29 Prague, Czech Republic 00019 * 00020 * This program is free software; you can redistribute it and/or modify 00021 * it under the terms of the GNU General Public License as published by 00022 * the Free Software Foundation; either version 2 of the License, or 00023 * (at your option) any later version. 00024 * 00025 * This program is distributed in the hope that it will be useful, 00026 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00027 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00028 * GNU General Public License for more details. 00029 * 00030 * You should have received a copy of the GNU General Public License 00031 * along with this program; if not, write to the Free Software 00032 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00033 */ 00034 /* 00035 * The original idea for this class comes from 00036 * Dubois-Pelerin, Y.: "Object-Oriented Finite Elements: Programming concepts and Implementation", 00037 * PhD Thesis, EPFL, Lausanne, 1992. 00038 */ 00039 00040 #include "flotarry.h" 00041 #include "intarray.h" 00042 #include "flotmtrx.h" 00043 #include "mathfem.h" 00044 #include "error.h" 00045 #include "datastream.h" 00046 #include "classtype.h" 00047 #include "mathfem.h" 00048 #include "freestor.h" 00049 00050 #include <cstdarg> 00051 00052 #ifdef __PARALLEL_MODE 00053 #include "combuff.h" 00054 #endif 00055 00056 namespace oofem { 00057 FloatArray :: FloatArray(int n) 00058 // Constructor : creates an array of size n (filled with garbage). 00059 { 00060 allocatedSize = size = n; 00061 if ( size ) { 00062 values = allocDouble(size); 00063 #ifdef DEBUG 00064 if ( !values ) { 00065 OOFEM_FATAL2("FloatArray :: FloatArray - Failed in allocating %d doubles", n); 00066 } 00067 00068 #endif 00069 } else { 00070 values = NULL; 00071 } 00072 } 00073 00074 FloatArray :: FloatArray(const FloatArray &src) 00075 { 00076 // copy constructor 00077 00078 double *srcVal; 00079 00080 allocatedSize = size = src.size; 00081 if ( size ) { 00082 values = allocDouble(size); 00083 #ifdef DEBUG 00084 if ( !values ) { 00085 OOFEM_FATAL2("FloatArray :: FloatArray - Failed in allocating %d doubles", size); 00086 } 00087 00088 #endif 00089 } else { 00090 values = NULL; 00091 } 00092 00093 srcVal = src.values; 00094 for ( int i = 0; i < size; i++ ) { 00095 this->values [ i ] = srcVal [ i ]; 00096 } 00097 } 00098 00099 FloatArray :: ~FloatArray() 00100 { 00101 if ( values ) { 00102 freeDouble(values); 00103 } 00104 } 00105 00106 FloatArray & 00107 FloatArray :: operator = ( const FloatArray & src ) 00108 { 00109 if ( this != & src ) { // beware of s=s; 00110 this->resize(src.size); 00111 for ( int i = 0; i < this->size; i++ ) { 00112 this->values [ i ] = src.values [ i ]; 00113 } 00114 } 00115 00116 return * this; 00117 } 00118 00119 #ifdef DEBUG 00120 double & 00121 FloatArray :: operator()(int i) 00122 { 00123 if ( i >= size ) { 00124 OOFEM_ERROR2("FloatArray :: operator() : array error on index : %d <= 0 \n", i); 00125 } 00126 return values [ i ]; 00127 } 00128 00129 const double & 00130 FloatArray :: operator()(int i) const 00131 { 00132 if ( i >= size ) { 00133 OOFEM_ERROR2("FloatArray :: operator() : array error on index : %d <= 0 \n", i); 00134 } 00135 return values [ i ]; 00136 } 00137 #endif 00138 00139 00140 void 00141 FloatArray :: setValues(int n, ...) 00142 { 00143 va_list vl; 00144 va_start(vl,n); 00145 this->resize(n); 00146 for (int i = 0; i < n; i++ ) { 00147 this->values [ i ] = va_arg(vl, double); 00148 } 00149 va_end(vl); 00150 } 00151 00152 00153 void 00154 FloatArray :: beScaled(double s, const FloatArray &b) 00155 { 00156 this->resize(b.size); 00157 for ( int i = 0; i < this->size; ++i ) { 00158 this->values [ i ] = s * b.values [ i ]; 00159 } 00160 } 00161 00162 00163 void FloatArray :: add(const FloatArray &b) 00164 // Performs the operation a=a+b, where a stands for the receiver. If the 00165 // receiver's size is 0, adjusts its size to that of b. Returns the 00166 // receiver. 00167 { 00168 if ( b.size == 0 ) { 00169 return; 00170 } 00171 00172 if ( !size ) { 00173 * this = b; 00174 return; 00175 } 00176 00177 if ( size != b.size ) { 00178 OOFEM_ERROR3("FloatArray :: add : dimension mismatch in a[%d]->add(b[%d])\n", size, b.size); 00179 } 00180 00181 for ( int i = 0; i < this->size; i++ ) { 00182 this->values [ i ] += b.values [ i ]; 00183 } 00184 } 00185 00186 00187 void FloatArray :: add(double offset) 00188 { 00189 for ( int i = 0; i < this->size; i++ ) { 00190 this->values [ i ] += offset; 00191 } 00192 } 00193 00194 00195 void FloatArray :: add(const double factor, const FloatArray &b) 00196 // Performs the operation a=a+factor*b, where a stands for the receiver. If the 00197 // receiver's size is 0, adjusts its size to that of b. 00198 { 00199 if ( this->size == 0 ) { 00200 this->beScaled(factor, b); 00201 return; 00202 } 00203 00204 # ifdef DEBUG 00205 if ( size != b.size ) { 00206 OOFEM_ERROR3("FloatArray :: add : dimension mismatch in a[%d]->add(b[%d])\n", size, b.size); 00207 } 00208 00209 # endif 00210 00211 for ( int i = 0; i < this->size; ++i ) { 00212 this->values [ i ] += factor * b.values [ i ]; 00213 } 00214 } 00215 00216 void FloatArray :: subtract(const FloatArray &src) 00217 // Performs the operation a=a-src, where a stands for the receiver. If the 00218 // receiver's size is 0, adjusts its size to that of src. 00219 { 00220 if ( src.giveSize() == 0 ) { 00221 return; 00222 } 00223 00224 if ( !size ) { 00225 this->resize(src.size); 00226 for ( int i = 0; i < this->size; ++i ) { 00227 this->values [ i ] = -src.values [ i ]; 00228 } 00229 00230 return; 00231 } 00232 00233 # ifdef DEBUG 00234 if ( this->size != src.size ) { 00235 OOFEM_ERROR3("FloatArray dimension mismatch in a[%d]->add(b[%d])\n", size, src.size); 00236 } 00237 00238 # endif 00239 00240 for ( int i = 0; i < this->size; ++i ) { 00241 this->values [ i ] -= src.values [ i ]; 00242 } 00243 } 00244 00245 00246 void FloatArray :: beMaxOf(const FloatArray &a, const FloatArray &b) 00247 { 00248 int n = a.giveSize(); 00249 00250 # ifdef DEBUG 00251 if ( n != b.size ) { 00252 OOFEM_ERROR3("FloatArray dimension mismatch in beMaxOf(a[%d],b[%d])\n", n, b.size); 00253 } 00254 00255 # endif 00256 00257 this->resize(n); 00258 for ( int i = 0; i < n; i++ ) { 00259 this->values [ i ] = max( a(i), b(i) ); 00260 } 00261 } 00262 00263 00264 void FloatArray :: beMinOf(const FloatArray &a, const FloatArray &b) 00265 { 00266 int n = a.giveSize(); 00267 00268 # ifdef DEBUG 00269 if ( n != b.size ) { 00270 OOFEM_ERROR3("FloatArray dimension mismatch in beMinOf(a[%d],b[%d])\n", n, b.size); 00271 } 00272 00273 # endif 00274 00275 this->resize(n); 00276 for ( int i = 0; i < n; i++ ) { 00277 this->values [ i ] = min( a(i), b(i) ); 00278 } 00279 } 00280 00281 00282 void FloatArray :: beDifferenceOf(const FloatArray &a, const FloatArray &b) 00283 { 00284 #ifdef DEBUG 00285 if ( a.size != b.size ) { 00286 OOFEM_ERROR3("FloatArray :: beDifferenceOf - size mismatch (%d : %d)", a.size, b.size); 00287 } 00288 00289 #endif 00290 this->resize(a.size); 00291 for ( int i = 0; i < this->size; ++i ) { 00292 this->values [ i ] = a.values [ i ] - b.values [ i ]; 00293 } 00294 } 00295 00296 void FloatArray :: beDifferenceOf(const FloatArray &a, const FloatArray &b, int n) 00297 { 00298 #ifdef DEBUG 00299 if ( a.size < n || b.size < n ) { 00300 OOFEM_ERROR3("FloatArray :: beDifferenceOf - wrong size ", a.size, b.size); 00301 } 00302 00303 #endif 00304 this->resize(n); 00305 for ( int i = 0; i < n; ++i ) { 00306 this->values [ i ] = a.values [ i ] - b.values [ i ]; 00307 } 00308 } 00309 00310 00311 void FloatArray :: beSubArrayOf(const FloatArray &src, const IntArray &indx) 00312 // 00313 // returns subVector from receiver 00314 // subVector size will be indx max val size 00315 // and on i-th position of subVector will be this->at(indx->at(i)) 00316 // 00317 { 00318 int i, ii, n, isize; 00319 00320 n = indx.giveSize(); 00321 00322 #ifdef DEBUG 00323 if ( src.size != n ) { 00324 OOFEM_ERROR("FloatArray :: beSubArrayOf - size mismatch"); 00325 } 00326 00327 #endif 00328 00329 for ( isize = 0, i = 0; i < n; i++ ) { 00330 if ( indx(i) > isize ) { 00331 isize = indx(i); 00332 } 00333 } 00334 00335 this->resize(isize); 00336 for ( i = 0; i < n; i++ ) { 00337 ii = indx(i); 00338 if ( ii > 0 ) { 00339 this->values [ ii-1 ] = src.values [ i ]; 00340 } 00341 } 00342 } 00343 00344 00345 void FloatArray :: addSubVector(const FloatArray &src, int si) 00346 { 00347 int i, reqSize, n = src.giveSize(); 00348 00349 si--; 00350 reqSize = si + n; 00351 if ( this->giveSize() < reqSize ) { 00352 this->resize(reqSize); 00353 } 00354 00355 for ( i = 1; i <= n; i++ ) { 00356 this->at(si + i) += src.at(i); 00357 } 00358 } 00359 00360 00361 void FloatArray :: beVectorProductOf(const FloatArray &v1, const FloatArray &v2) 00362 { 00363 // check proper bounds 00364 if ( ( v1.giveSize() != 3 ) || ( v2.giveSize() != 3 ) ) { 00365 OOFEM_ERROR(" FloatArray::VectorProduct : size mismatch, size is not equal to 3"); 00366 } 00367 00368 this->resize(3); 00369 00370 this->at(1) = v1.at(2) * v2.at(3) - v1.at(3) * v2.at(2); 00371 this->at(2) = v1.at(3) * v2.at(1) - v1.at(1) * v2.at(3); 00372 this->at(3) = v1.at(1) * v2.at(2) - v1.at(2) * v2.at(1); 00373 } 00374 00375 00376 double FloatArray :: dotProduct(const FloatArray &x) const 00377 { 00378 # ifdef DEBUG 00379 if ( this->size != x.size ) { 00380 OOFEM_ERROR3("FloatArray :: dotProduct : dimension mismatch in a[%d]->dotProduct(b[%d])\n", this->size, x.size); 00381 } 00382 00383 # endif 00384 00385 double dp = 0; 00386 for ( int i = 0; i < this->size; i++ ) { 00387 dp += this->values [ i ] * x.values [ i ]; 00388 } 00389 00390 return dp; 00391 } 00392 00393 00394 double FloatArray :: dotProduct(const FloatArray &x, int size) const 00395 { 00396 # ifdef DEBUG 00397 if ( size > this->size || size > x.size ) { 00398 OOFEM_ERROR3("FloatArray :: dotProduct : dimension mismatch in a[%d]->dotProduct(b[%d])\n", this->size, x.size); 00399 } 00400 00401 # endif 00402 00403 double dp = 0.; 00404 for ( int i = 0; i < size; i++ ) { 00405 dp += this->values [ i ] * x.values [ i ]; 00406 } 00407 00408 return dp; 00409 } 00410 00411 00412 double FloatArray :: distance(const FloatArray &x) const 00413 { 00414 return sqrt( this->distance_square(x) ); 00415 } 00416 00417 00418 double FloatArray :: distance_square(const FloatArray &from) const 00419 // returns distance between receiver and from from 00420 // computed using generalized pythagorean formulae 00421 { 00422 double *p1, *p2, dx, dist = 0.; 00423 00424 p1 = this->values; 00425 p2 = from.values; 00426 int s = min(size, from.size); 00427 while ( s-- ) { 00428 dx = ( * p1 ) - ( * p2 ); 00429 dist += dx * dx; 00430 p1++; 00431 p2++; 00432 } 00433 00434 return dist; 00435 } 00436 00437 00438 void FloatArray :: assemble(const FloatArray &fe, const IntArray &loc) 00439 // Assembles the array fe (typically, the load vector of a finite 00440 // element) to the receiver, using loc as location array. 00441 { 00442 int n = fe.giveSize(); 00443 # ifdef DEBUG 00444 if ( n != loc.giveSize() ) { 00445 OOFEM_ERROR3("FloatArray::assemble : dimensions of 'fe' (%d) and 'loc' (%d) mismatch",fe.giveSize(), loc.giveSize()); 00446 } 00447 00448 # endif 00449 00450 for ( int i = 1; i <= n; i++ ) { 00451 int ii = loc.at(i); 00452 if ( ii ) { // if non 0 coefficient, 00453 this->at(ii) += fe.at(i); 00454 } 00455 } 00456 00457 } 00458 00459 00460 #ifdef DEBUG 00461 double &FloatArray :: at(int i) 00462 // Returns the i-th coefficient of the receiver. Slow but safe. 00463 { 00464 this->checkBounds(i); 00465 return values [ i - 1 ]; 00466 } 00467 00468 double FloatArray :: at(int i) const 00469 // Returns the i-th coefficient of the receiver. Slow but safe. 00470 { 00471 this->checkBounds(i); 00472 return values [ i - 1 ]; 00473 } 00474 #endif 00475 00476 00477 #ifdef DEBUG 00478 void FloatArray :: checkBounds(int i) const 00479 // Checks that the receiver's size is not smaller than 'i'. 00480 { 00481 if ( i <= 0 ) { 00482 OOFEM_ERROR2("FloatArray :: checkBounds : array error on index : %d <= 0 \n", i); 00483 } 00484 00485 if ( i > size ) { 00486 OOFEM_ERROR3("FloatArray :: checkBounds : array error on index : %d > %d \n", i, size); 00487 } 00488 } 00489 #endif 00490 00491 00492 void FloatArray :: checkSizeTowards(const IntArray &loc) 00493 // Expands the receiver if loc points to coefficients beyond the size of 00494 // the receiver. 00495 { 00496 int n, high; 00497 00498 high = 0; 00499 n = loc.giveSize(); 00500 for ( int i = 1; i <= n; i++ ) { 00501 high = max( high, ( loc.at(i) ) ); 00502 } 00503 00504 if ( high > size ) { // receiver must be expanded 00505 this->resize(high); 00506 } 00507 } 00508 00509 00510 void FloatArray :: resize(int n, int allocChunk) 00511 { 00512 int i; 00513 double *newValues, *p1, *p2; 00514 00515 #ifdef DEBUG 00516 if ( allocChunk < 0 ) { 00517 OOFEM_FATAL2("FloatArray :: resize - allocChunk must be non-negative; %d", allocChunk); 00518 } 00519 00520 #endif 00521 00522 if ( n <= allocatedSize ) { 00523 size = n; 00524 return; 00525 } 00526 00527 newValues = allocDouble(n + allocChunk); 00528 #ifdef DEBUG 00529 if ( !newValues ) { 00530 OOFEM_FATAL2("FloatArray :: resize - Failed in allocating %d doubles", n + allocChunk); 00531 } 00532 00533 #endif 00534 p1 = values; 00535 p2 = newValues; 00536 i = size; 00537 while ( i-- ) { 00538 * p2++ = * p1++; 00539 } 00540 00541 if ( values ) { 00542 freeDouble(values); 00543 } 00544 00545 values = newValues; 00546 allocatedSize = n + allocChunk; 00547 size = n; 00548 } 00549 00550 00551 void FloatArray :: hardResize(int n) 00552 // Reallocates the receiver with new size. 00553 { 00554 int i; 00555 double *newValues, *p1, *p2; 00556 00557 // if (n <= allocatedSize) {size = n; return;} 00558 00559 newValues = allocDouble(n); 00560 #ifdef DEBUG 00561 if ( !newValues ) { 00562 OOFEM_FATAL2("FloatArray :: hardResize - Failed in allocating %d doubles", n); 00563 } 00564 00565 #endif 00566 p1 = values; 00567 p2 = newValues; 00568 i = min(size, n); 00569 while ( i-- ) { 00570 * p2++ = * p1++; 00571 } 00572 00573 if ( values ) { 00574 freeDouble(values); 00575 } 00576 00577 values = newValues; 00578 allocatedSize = size = n; 00579 } 00580 00581 00582 00583 bool FloatArray :: containsOnlyZeroes() const 00584 { 00585 for ( int i = 0; i < this->size; i++ ) { 00586 if ( this->values [ i ] != 0. ) { 00587 return false; 00588 } 00589 } 00590 00591 return true; 00592 } 00593 00594 00595 void FloatArray :: zero() 00596 { 00597 for ( int i = 0; i < this->size; i++ ) { 00598 this->values [ i ] = 0.; 00599 } 00600 } 00601 00602 00603 void FloatArray :: beProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray) 00604 // Stores the product of aMatrix * anArray in to receiver 00605 { 00606 int nColumns, nRows; 00607 double sum; 00608 00609 # ifdef DEBUG 00610 if ( ( nColumns = aMatrix.giveNumberOfColumns() ) - anArray.giveSize() ) { 00611 OOFEM_ERROR("FloatArray :: beProductOf : dimension mismatch"); 00612 } 00613 00614 # endif 00615 00616 nColumns = aMatrix.giveNumberOfColumns(); 00617 this->resize( nRows = aMatrix.giveNumberOfRows() ); 00618 for ( int i = 1; i <= nRows; i++ ) { 00619 sum = 0.; 00620 for ( int j = 1; j <= nColumns; j++ ) { 00621 sum += aMatrix.at(i, j) * anArray.at(j); 00622 } 00623 00624 this->at(i) = sum; 00625 } 00626 } 00627 00628 00629 void FloatArray :: beTProductOf(const FloatMatrix &aMatrix, const FloatArray &anArray) 00630 // Stores the product of aMatrix^T * anArray in to receiver 00631 { 00632 int nColumns, nRows; 00633 double sum; 00634 00635 # ifdef DEBUG 00636 if ( ( nColumns = aMatrix.giveNumberOfRows() ) - anArray.giveSize() ) { 00637 OOFEM_ERROR("FloatArray :: beTProductOf : dimension mismatch"); 00638 } 00639 00640 # endif 00641 00642 nColumns = aMatrix.giveNumberOfRows(); 00643 this->resize( nRows = aMatrix.giveNumberOfColumns() ); 00644 for ( int i = 1; i <= nRows; i++ ) { 00645 sum = 0.; 00646 for ( int j = 1; j <= nColumns; j++ ) { 00647 sum += aMatrix.at(j, i) * anArray.at(j); 00648 } 00649 00650 this->at(i) = sum; 00651 } 00652 } 00653 00654 00655 void FloatArray :: negated() 00656 { 00657 for ( int i = 0; i < this->size; i++ ) { 00658 this->values [ i ] = -this->values [ i ]; 00659 } 00660 } 00661 00662 00663 void FloatArray :: printYourself() const 00664 // Prints the receiver on screen. 00665 { 00666 printf("FloatArray of size : %d \n", size); 00667 for ( int i = 1; i <= size; ++i ) { 00668 printf( "%10.3e ", this->at(i) ); 00669 } 00670 00671 printf("\n"); 00672 } 00673 00674 00675 void FloatArray :: pY() const 00676 // Prints the receiver on screen with higher accuracy than printYourself. 00677 { 00678 printf("["); 00679 for ( int i = 1; i <= size; ++i ) { 00680 printf( "%20.14e; ", this->at(i) ); 00681 } 00682 00683 printf("];\n"); 00684 } 00685 00686 00687 void FloatArray :: rotatedWith(FloatMatrix &r, char mode) 00688 // Returns the receiver 'a' rotated according the change-of-base matrix r. 00689 // If mode = 't', the method performs the operation a = r(transp) * a . 00690 // If mode = 'n', the method performs the operation a = r * a . 00691 { 00692 FloatArray rta; 00693 00694 if ( mode == 't' ) { 00695 rta.beTProductOf(r, * this); 00696 } else if ( mode == 'n' ) { 00697 rta.beProductOf(r, * this); 00698 } else { 00699 OOFEM_ERROR("FloatArray :: rotatedWith: unsupported mode"); 00700 } 00701 00702 * this = rta; 00703 } 00704 00705 00706 void FloatArray :: times(double factor) 00707 // Multiplies every coefficient of the receiver by factor. 00708 { 00709 for ( int i = 0; i < this->size; i++ ) { 00710 this->values [ i ] *= factor; 00711 } 00712 } 00713 00714 00715 double FloatArray :: normalize() 00716 { 00717 double norm = this->computeNorm(); 00718 if ( norm < 1.e-80 ) { 00719 OOFEM_ERROR("FloatArray::normalize : cannot norm receiver, norm is too small"); 00720 } 00721 00722 this->times(1. / norm); 00723 return norm; 00724 } 00725 00726 00727 double FloatArray :: computeNorm() const 00728 { 00729 return sqrt( this->computeSquaredNorm() ); 00730 } 00731 00732 00733 double FloatArray :: computeSquaredNorm() const 00734 { 00735 int i; 00736 double *p, norm2 = 0.; 00737 00738 p = this->values; 00739 i = this->size; 00740 while ( i-- ) { 00741 norm2 += ( * p ) * ( * p ); 00742 p++; 00743 } 00744 00745 return norm2; 00746 } 00747 00748 00749 double FloatArray :: sum() const 00750 { 00751 int i; 00752 double *p, sum = 0; 00753 00754 p = this->values; 00755 i = this->size; 00756 while ( i-- ) { 00757 sum += * ( p++ ); 00758 } 00759 00760 return sum; 00761 } 00762 00763 void FloatArray :: copySubVector(const FloatArray &src, int si) 00764 { 00765 int i, reqSize, n = src.giveSize(); 00766 00767 si--; 00768 reqSize = si + n; 00769 if ( this->giveSize() < reqSize ) { 00770 this->resize(reqSize); 00771 } 00772 00773 for ( i = 1; i <= n; i++ ) { 00774 this->at(si + i) = src.at(i); 00775 } 00776 } 00777 00778 00779 contextIOResultType FloatArray :: storeYourself(DataStream *stream, ContextMode mode) 00780 // writes receiver's binary image into stream 00781 // use id to distinguish some instances 00782 // return value >0 success 00783 // =0 file i/o error 00784 { 00785 // write size 00786 if ( !stream->write(& size, 1) ) { 00787 return CIO_IOERR; 00788 } 00789 00790 // write raw data 00791 if ( size ) { 00792 if ( !stream->write(values, size) ) { 00793 return CIO_IOERR; 00794 } 00795 } 00796 00797 // return result back 00798 return CIO_OK; 00799 } 00800 00801 contextIOResultType FloatArray :: restoreYourself(DataStream *stream, ContextMode mode) 00802 // reads receiver from stream 00803 // warning - overwrites existing data! 00804 // returns 0 if file i/o error 00805 // -1 if id od class id is not correct 00806 { 00807 // read size 00808 if ( !stream->read(& size, 1) ) { 00809 return CIO_IOERR; 00810 } 00811 00812 if ( size > allocatedSize ) { 00813 if ( values != NULL ) { 00814 freeDouble(values); 00815 } 00816 00817 values = allocDouble(size); 00818 #ifdef DEBUG 00819 if ( !values ) { 00820 OOFEM_FATAL2("FloatArray :: restoreYourself - Failed in allocating %d doubles", size); 00821 } 00822 00823 #endif 00824 allocatedSize = size; 00825 } 00826 00827 // read raw data 00828 if ( size ) { 00829 if ( !stream->read(values, size) ) { 00830 return CIO_IOERR; 00831 } 00832 } 00833 00834 // return result back 00835 return CIO_OK; 00836 } 00837 00838 00839 #ifdef __PARALLEL_MODE 00840 int FloatArray :: packToCommBuffer(CommunicationBuffer &buff) const 00841 { 00842 int result = 1; 00843 // pack size 00844 result &= buff.packInt(size); 00845 // pack data 00846 result &= buff.packArray(this->values, size); 00847 00848 return result; 00849 } 00850 00851 int FloatArray :: unpackFromCommBuffer(CommunicationBuffer &buff) 00852 { 00853 int newSize, result = 1; 00854 // unpack size 00855 result &= buff.unpackInt(newSize); 00856 // resize yourself 00857 this->resize(newSize); 00858 result &= buff.unpackArray(this->values, newSize); 00859 00860 return result; 00861 } 00862 00863 int FloatArray :: givePackSize(CommunicationBuffer &buff) const 00864 { 00865 return buff.givePackSize(MPI_INT, 1) + buff.givePackSize(MPI_DOUBLE, this->size); 00866 } 00867 00868 #endif 00869 00870 #ifdef IML_COMPAT 00871 00872 FloatArray &FloatArray :: operator = ( const double & val ) 00873 { 00874 for ( int i = 0; i < size; i++ ) { 00875 values [ i ] = val; 00876 } 00877 00878 return * this; 00879 } 00880 00881 FloatArray &operator *= ( FloatArray & x, const double & a ) 00882 { 00883 int N = x.giveSize(); 00884 for ( int i = 0; i < N; i++ ) { 00885 x(i) *= a; 00886 } 00887 00888 return x; 00889 } 00890 00891 00892 FloatArray operator *( const double & a, const FloatArray & x ) 00893 { 00894 int N = x.giveSize(); 00895 FloatArray result(N); 00896 for ( int i = 0; i < N; i++ ) { 00897 result(i) = x(i) * a; 00898 } 00899 00900 return result; 00901 } 00902 00903 FloatArray operator *( const FloatArray & x, const double & a ) 00904 { 00905 // This is the other commutative case of vector*scalar. 00906 // It should be just defined to be 00907 // "return operator*(a,x);" 00908 // but some compilers (e.g. Turbo C++ v.3.0) have trouble 00909 // determining the proper template match. For the moment, 00910 // we'll just duplicate the code in the scalar * vector 00911 // case above. 00912 00913 int N = x.giveSize(); 00914 FloatArray result(N); 00915 for ( int i = 0; i < N; i++ ) { 00916 result(i) = x(i) * a; 00917 } 00918 00919 return result; 00920 } 00921 00922 FloatArray operator + ( const FloatArray & x, const FloatArray & y ) 00923 { 00924 int N = x.giveSize(); 00925 #if DEBUG 00926 if ( N != y.giveSize() ) { 00927 OOFEM_ERROR("loatArray operator+ : incompatible vector lengths"); 00928 } 00929 #endif 00930 00931 FloatArray result(N); 00932 for ( int i = 0; i < N; i++ ) { 00933 result(i) = x(i) + y(i); 00934 } 00935 00936 return result; 00937 } 00938 00939 FloatArray operator - ( const FloatArray & x, const FloatArray & y ) 00940 { 00941 int N = x.giveSize(); 00942 #if DEBUG 00943 if ( N != y.giveSize() ) { 00944 OOFEM_ERROR("FloatArray operator- : incompatible vector lengths"); 00945 } 00946 #endif 00947 00948 FloatArray result(N); 00949 for ( int i = 0; i < N; i++ ) { 00950 result(i) = x(i) - y(i); 00951 } 00952 00953 return result; 00954 } 00955 00956 00957 FloatArray &operator += ( FloatArray & x, const FloatArray & y ) 00958 { 00959 int N = x.giveSize(); 00960 #if DEBUG 00961 if ( N != y.giveSize() ) { 00962 OOFEM_ERROR("FloatArray& operator+= : incompatible vector lengths"); 00963 } 00964 #endif 00965 00966 for ( int i = 0; i < N; i++ ) { 00967 x(i) += y(i); 00968 } 00969 00970 return x; 00971 } 00972 00973 00974 FloatArray &operator -= ( FloatArray & x, const FloatArray & y ) 00975 { 00976 int N = x.giveSize(); 00977 #if DEBUG 00978 if ( N != y.giveSize() ) { 00979 OOFEM_ERROR("FloatArray& operator-= : incompatible vector lengths"); 00980 } 00981 #endif 00982 00983 for ( int i = 0; i < N; i++ ) { 00984 x(i) -= y(i); 00985 } 00986 00987 return x; 00988 } 00989 00990 00991 double dot(const FloatArray &x, const FloatArray &y) 00992 { 00993 // Check for compatible dimensions: 00994 #if DEBUG 00995 if ( x.giveSize() != y.giveSize() ) { 00996 OOFEM_ERROR("dot : incompatible dimensions"); 00997 } 00998 #endif 00999 01000 double temp = 0; 01001 for ( int i = 0; i < x.giveSize(); i++ ) { 01002 temp += x(i) * y(i); 01003 } 01004 01005 return temp; 01006 } 01007 01008 double norm(const FloatArray &x) 01009 { 01010 double temp = oofem :: dot(x, x); 01011 return sqrt(temp); 01012 } 01013 01014 #endif 01015 01016 void FloatArray :: beFullVectorForm(const FloatMatrix &aMatrix) 01017 { 01018 // Revrites the matrix on vector form, order: 11, 22, 33, 23, 13, 12, 32, 31, 21 01019 # ifdef DEBUG 01020 if ( aMatrix.giveNumberOfColumns() || aMatrix.giveNumberOfColumns() !=3) { 01021 OOFEM_ERROR("FloatArray :: beFullVectorForm : matrix dimension is not 3x3"); 01022 } 01023 01024 # endif 01025 this->resize(9); 01026 this->at(1) = aMatrix.at(1,1); this->at(2) = aMatrix.at(2,2); this->at(3) = aMatrix.at(3,3); 01027 this->at(4) = aMatrix.at(2,3); this->at(5) = aMatrix.at(1,3); this->at(6) = aMatrix.at(1,2); 01028 this->at(7) = aMatrix.at(3,2); this->at(8) = aMatrix.at(3,1); this->at(9) = aMatrix.at(2,1); 01029 } 01030 01031 void FloatArray :: beReducedVectorForm(const FloatMatrix &aMatrix) 01032 { 01033 // Revrites the matrix on vector form (symmetrized matrix used), order: 11, 22, 33, 23, 13, 12 01034 # ifdef DEBUG 01035 if ( aMatrix.giveNumberOfColumns() !=3 || aMatrix.giveNumberOfColumns() !=3) { 01036 OOFEM_ERROR("FloatArray :: beReducedVectorForm : matrix dimension is not 3x3"); 01037 } 01038 01039 # endif 01040 01041 this->resize(6); 01042 this->at(1) = aMatrix.at(1,1); this->at(2) = aMatrix.at(2,2); this->at(3) = aMatrix.at(3,3); 01043 this->at(4) = 0.5*( aMatrix.at(2,3) + aMatrix.at(3,2) ); 01044 this->at(5) = 0.5*( aMatrix.at(1,3) + aMatrix.at(3,1) ); 01045 this->at(6) = 0.5*( aMatrix.at(1,2) + aMatrix.at(2,1) ); 01046 } 01047 01048 01049 } // end namespace oofem