|
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 #include "sprnodalrecoverymodel.h" 00036 #include "timestep.h" 00037 #include "element.h" 00038 #include "node.h" 00039 #include "conTable.h" 00040 #include "integrationrule.h" 00041 #include "gausspnt.h" 00042 00043 #include <list> 00044 00045 namespace oofem { 00046 SPRNodalRecoveryModel :: SPRNodalRecoveryModel(Domain *d) : NodalRecoveryModel(d) 00047 { } 00048 00049 SPRNodalRecoveryModel :: ~SPRNodalRecoveryModel() 00050 { } 00051 00052 int 00053 SPRNodalRecoveryModel :: recoverValues(InternalStateType type, TimeStep *tStep) 00054 { 00055 int nregions = this->giveNumberOfVirtualRegions(); 00056 int nnodes = domain->giveNumberOfDofManagers(); 00057 int regionValSize; 00058 int regionDofMans; 00059 int neq, eq, npap, papNumber; 00060 IntArray skipRegionMap(nregions), regionRecSize(nregions); 00061 IntArray regionNodalNumbers(nnodes); 00062 IntArray patchElems, dofManToDetermine, pap, regionTypes; 00063 SPRPatchType regType; 00064 FloatMatrix a; 00065 FloatArray dofManValues; 00066 IntArray dofManPatchCount; 00067 00068 if ( ( this->valType == type ) && ( this->stateCounter == tStep->giveSolutionStateCounter() ) ) { 00069 return 1; 00070 } 00071 00072 #ifdef __PARALLEL_MODE 00073 this->initCommMaps(); 00074 #endif 00075 00076 // clear nodal table 00077 this->clear(); 00078 00079 // init region table indicating regions to skip 00080 this->initRegionMap(skipRegionMap, regionRecSize, regionTypes, type); 00081 00082 #ifdef __PARALLEL_MODE 00083 // synchronize skipRegionMap over all cpus 00084 IntArray temp_skipRegionMap(skipRegionMap); 00085 MPI_Allreduce(temp_skipRegionMap.givePointer(), skipRegionMap.givePointer(), nregions, MPI_INT, MPI_LOR, MPI_COMM_WORLD); 00086 #endif 00087 00088 // loop over regions 00089 for (int ireg = 1; ireg <= nregions; ireg++ ) { 00090 // skip regions 00091 if ( skipRegionMap.at(ireg) ) { 00092 continue; 00093 } 00094 00095 regType = ( SPRPatchType ) regionTypes.at(ireg); 00096 regionValSize = regionRecSize.at(ireg); 00097 // loop over elements and determine local region node numbering and determine and check nodal values size 00098 if ( this->initRegionNodeNumbering(regionNodalNumbers, regionDofMans, ireg) == 0 ) { 00099 continue; 00100 } 00101 00102 neq = regionDofMans * regionValSize; 00103 dofManValues.resize(neq); 00104 dofManValues.zero(); 00105 dofManPatchCount.resize(regionDofMans); 00106 dofManPatchCount.zero(); 00107 00108 //pap = patch assembly points 00109 this->determinePatchAssemblyPoints(pap, ireg, regType); 00110 00111 npap = pap.giveSize(); 00112 for (int ipap = 1; ipap <= npap; ipap++ ) { 00113 papNumber = pap.at(ipap); 00114 00115 this->initPatch(patchElems, dofManToDetermine, pap, papNumber, ireg); 00116 this->computePatch(a, patchElems, papNumber, regionValSize, regType, type, tStep); 00117 this->determineValuesFromPatch(dofManValues, dofManPatchCount, regionNodalNumbers, 00118 dofManToDetermine, a, papNumber, regionValSize, regType); 00119 } 00120 00121 #ifdef __PARALLEL_MODE 00122 this->exchangeDofManValues(ireg, dofManValues, dofManPatchCount, regionNodalNumbers, regionValSize); 00123 #endif 00124 00125 // average recovered values of active region 00126 bool abortFlag = false; 00127 for (int i = 1; i <= nnodes; i++ ) { 00128 #ifndef __PARALLEL_MODE 00129 if ( regionNodalNumbers.at(i) ) { 00130 #else 00131 if ( regionNodalNumbers.at(i) && 00132 ( ( domain->giveDofManager(i)->giveParallelMode() == DofManager_local ) || 00133 ( domain->giveDofManager(i)->giveParallelMode() == DofManager_shared ) ) ) { 00134 #endif 00135 eq = ( regionNodalNumbers.at(i) - 1 ) * regionValSize; 00136 if ( dofManPatchCount.at( regionNodalNumbers.at(i) ) ) { 00137 for (int j = 1; j <= regionValSize; j++ ) { 00138 dofManValues.at(eq + j) /= dofManPatchCount.at( regionNodalNumbers.at(i) ); 00139 } 00140 } else { 00141 #ifndef __PARALLEL_MODE 00142 OOFEM_WARNING3("SPRNodalRecoveryModel::recoverValues : values of %s in dofmanager %d undetermined", __InternalStateTypeToString(type), i); 00143 #else 00144 OOFEM_WARNING4("[%d] SPRNodalRecoveryModel::recoverValues : values of %s in dofmanager %d undetermined", 00145 domain->giveEngngModel()->giveRank(), __InternalStateTypeToString(type), i); 00146 #endif 00147 for (int j = 1; j <= regionValSize; j++ ) { 00148 dofManValues.at(eq + j) = 0.0; 00149 } 00150 //abortFlag = true; 00151 } 00152 } 00153 } 00154 00155 if ( abortFlag ) { 00156 abort(); 00157 } 00158 00159 // update recovered values 00160 this->updateRegionRecoveredValues(ireg, regionNodalNumbers, regionValSize, dofManValues); 00161 } 00162 00163 this->valType = type; 00164 this->stateCounter = tStep->giveSolutionStateCounter(); 00165 return 1; 00166 } 00167 00168 void 00169 SPRNodalRecoveryModel :: initRegionMap(IntArray ®ionMap, IntArray ®ionValSize, 00170 IntArray ®ionTypes, InternalStateType type) 00171 { 00172 int nregions = this->giveNumberOfVirtualRegions(); 00173 int ielem, nelem = domain->giveNumberOfElements(); 00174 int i, regionsSkipped = 0; 00175 int elemVR; 00176 Element *element; 00177 SPRNodalRecoveryModelInterface *interface; 00178 00179 regionMap.resize(nregions); 00180 regionMap.zero(); 00181 regionValSize.resize(nregions); 00182 regionValSize.zero(); 00183 regionTypes.resize(nregions); 00184 regionTypes.zero(); 00185 00186 // loop over elements and check if implement interface 00187 for ( ielem = 1; ielem <= nelem; ielem++ ) { 00188 element = domain->giveElement(ielem); 00189 if ( !element-> isActivated(domain->giveEngngModel()->giveCurrentStep()) ) { //skip inactivated elements 00190 continue; 00191 } 00192 #ifdef __PARALLEL_MODE 00193 if ( element->giveParallelMode() != Element_local ) { 00194 continue; 00195 } 00196 00197 #endif 00198 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) == NULL ) { 00199 // If an element doesn't implement the interface, it is ignored. 00200 //regionsSkipped = 1; 00201 //regionMap.at( element->giveRegionNumber() ) = 1; 00202 continue; 00203 } else { 00204 if ( ( elemVR = this->giveElementVirtualRegionNumber(ielem) ) ) { // test if elementVR is nonzero 00205 if ( regionValSize.at(elemVR) ) { 00206 if ( regionValSize.at(elemVR) != interface->SPRNodalRecoveryMI_giveDofManRecordSize(type) ) { 00207 // This indicates a size mis-match between different elements, no choice but to skip the region. 00208 regionMap.at(elemVR) = 1; 00209 regionsSkipped = 1; 00210 } 00211 00212 if ( regionTypes.at(elemVR) != ( int ) interface->SPRNodalRecoveryMI_givePatchType() ) { 00213 regionMap.at(elemVR) = 1; 00214 /* 00215 * printf ("NodalRecoveryModel :: initRegionMap: element %d has incompatible Patch type, skipping region\n",ielem); 00216 */ 00217 regionsSkipped = 1; 00218 } 00219 } else { 00220 regionValSize.at(elemVR) = interface->SPRNodalRecoveryMI_giveDofManRecordSize(type); 00221 regionTypes.at(elemVR) = ( int ) interface->SPRNodalRecoveryMI_givePatchType(); 00222 if ( regionValSize.at(elemVR) == 0 ) { 00223 regionMap.at(elemVR) = 1; 00224 regionsSkipped = 1; 00225 } 00226 } 00227 } 00228 } 00229 } 00230 00231 if ( regionsSkipped ) { 00232 OOFEM_LOG_RELEVANT( "SPRNodalRecoveryModel :: initRegionMap: skipping regions for InternalStateType %s\n", __InternalStateTypeToString(type) ); 00233 for ( i = 1; i <= nregions; i++ ) { 00234 if ( regionMap.at(i) ) { 00235 OOFEM_LOG_RELEVANT("%d ", i); 00236 } 00237 } 00238 00239 OOFEM_LOG_RELEVANT("\n"); 00240 } 00241 } 00242 00243 void 00244 SPRNodalRecoveryModel :: determinePatchAssemblyPoints(IntArray &pap, int ireg, SPRPatchType regType) 00245 { 00246 int idofMan, ndofMan = domain->giveNumberOfDofManagers(); 00247 int ielem, nelem = domain->giveNumberOfElements(); 00248 int npap, ipap, count, neq, nip; 00249 IntArray dofManFlags(ndofMan), elemPap; 00250 SPRNodalRecoveryModelInterface *interface; 00251 Element *element; 00252 const IntArray *papDofManConnectivity; 00253 enum { papStatus_noPap, papStatus_regular, papStatus_boundary, papStatus_littleNIPs }; 00254 00255 // init all dof man statuses 00256 for ( idofMan = 1; idofMan <= ndofMan; idofMan++ ) { 00257 dofManFlags.at(idofMan) = papStatus_noPap; 00258 } 00259 00260 // assign all possible paps with corresponding count 00261 for ( ielem = 1; ielem <= nelem; ielem++ ) { 00262 element = domain->giveElement(ielem); 00263 #ifdef __PARALLEL_MODE 00264 if ( element->giveParallelMode() != Element_local ) { 00265 continue; 00266 } 00267 00268 #endif 00269 if ( this->giveElementVirtualRegionNumber(ielem) != ireg ) { 00270 continue; 00271 } 00272 00273 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) ) { 00274 interface->SPRNodalRecoveryMI_giveSPRAssemblyPoints(elemPap); 00275 npap = elemPap.giveSize(); 00276 for ( ipap = 1; ipap <= npap; ipap++ ) { 00277 dofManFlags.at( elemPap.at(ipap) ) = papStatus_regular; 00278 } 00279 } 00280 } 00281 00282 // after loop all possible paps (patch assembly points) will have papStatus_regular flag 00283 00284 // but we now have to skip those pap reported by elements, which have not enough integration points 00285 // to determine the least square fit of patch 00286 // and also we mark those dofManagers which are on boundary 00287 00288 neq = this->giveNumberOfUnknownPolynomialCoefficients(regType); 00289 for ( idofMan = 1; idofMan <= ndofMan; idofMan++ ) { 00290 // mark boundary dofManagers 00291 if ( domain->giveDofManager(idofMan)->isBoundary() ) { 00292 dofManFlags.at(idofMan) = papStatus_boundary; 00293 } 00294 00295 nip = 0; 00296 if ( dofManFlags.at(idofMan) != papStatus_noPap ) { 00297 papDofManConnectivity = domain->giveConnectivityTable()->giveDofManConnectivityArray(idofMan); 00298 for ( ielem = 1; ielem <= papDofManConnectivity->giveSize(); ielem++ ) { 00299 element = domain->giveElement( papDofManConnectivity->at(ielem) ); 00300 #ifdef __PARALLEL_MODE 00301 if ( element->giveParallelMode() != Element_local ) { 00302 continue; 00303 } 00304 00305 #endif 00306 if ( this->giveElementVirtualRegionNumber( element->giveNumber() ) == ireg ) { 00307 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) ) { 00308 nip += interface->SPRNodalRecoveryMI_giveNumberOfIP(); 00309 } 00310 } 00311 } 00312 00313 if ( nip < neq ) { 00314 // this pap has not enough integration points to determine patch polynomial 00315 // reset its count to zero 00316 dofManFlags.at(idofMan) = papStatus_littleNIPs; 00317 } 00318 } 00319 } 00320 00321 // 00322 // generally boundary pap can be removed from pap list 00323 // if their value can be determined from other paps 00324 // and if they are not the last resort to determine other dofManagers values (for example those with little nips). 00325 // 00326 // 00327 // here only test if paps with papStatus_littleNIPs can be determined using regular paps (papStatus_regular) 00328 // or the boundary paps must be employed. In such case these boundary paps are marked as regular ones 00329 // to force paches to be assembled. 00330 // 00331 bool foundRegularPap, foundBoundaryPap, abort_flag = false; 00332 // loop over boundary candidates to remove and try to confirm whether they can be removed 00333 for ( idofMan = 1; idofMan <= ndofMan; idofMan++ ) { 00334 foundRegularPap = foundBoundaryPap = false; 00335 if ( dofManFlags.at(idofMan) == papStatus_littleNIPs ) { 00336 papDofManConnectivity = domain->giveConnectivityTable()->giveDofManConnectivityArray(idofMan); 00337 for ( ielem = 1; ielem <= papDofManConnectivity->giveSize(); ielem++ ) { 00338 // try to determine if they can be determined from surronuding elements paps 00339 element = domain->giveElement( papDofManConnectivity->at(ielem) ); 00340 #ifdef __PARALLEL_MODE 00341 if ( element->giveParallelMode() != Element_local ) { 00342 continue; 00343 } 00344 00345 #endif 00346 if ( this->giveElementVirtualRegionNumber( element->giveNumber() ) != ireg ) { 00347 continue; 00348 } 00349 00350 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) ) { 00351 interface->SPRNodalRecoveryMI_giveSPRAssemblyPoints(elemPap); 00352 npap = elemPap.giveSize(); 00353 for ( ipap = 1; ipap <= npap; ipap++ ) { 00354 // skip other dofMans with littleNIPs 00355 if ( dofManFlags.at( elemPap.at(ipap) ) == papStatus_littleNIPs ) { 00356 continue; 00357 } 00358 00359 if ( dofManFlags.at( elemPap.at(ipap) ) == papStatus_regular ) { 00360 foundRegularPap = true; 00361 } else if ( dofManFlags.at( elemPap.at(ipap) ) == papStatus_boundary ) { 00362 foundBoundaryPap = true; 00363 } 00364 } 00365 } 00366 } 00367 00368 if ( foundRegularPap ) { 00369 continue; // can be determined from regular pap - ok 00370 } 00371 00372 // boundary dof man can be removed <= can be determined 00373 if ( foundBoundaryPap ) { 00374 // try the last possibility-> determine its value from boundary patches 00375 // mark boundaryPap as regulars -> they can be used to assemble patch (they have enough nips) 00376 for ( ielem = 1; ielem <= papDofManConnectivity->giveSize(); ielem++ ) { 00377 element = domain->giveElement( papDofManConnectivity->at(ielem) ); 00378 if ( this->giveElementVirtualRegionNumber( element->giveNumber() ) != ireg ) { 00379 continue; 00380 } 00381 00382 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) ) { 00383 interface->SPRNodalRecoveryMI_giveSPRAssemblyPoints(elemPap); 00384 npap = elemPap.giveSize(); 00385 for ( ipap = 1; ipap <= npap; ipap++ ) { 00386 if ( dofManFlags.at( elemPap.at(ipap) ) == papStatus_boundary ) { 00387 // change status to regular pap 00388 dofManFlags.at( elemPap.at(ipap) ) = papStatus_regular; 00389 } 00390 } 00391 } 00392 } 00393 } else { 00394 // if the pap with papStatus_littleNIPs status found, which values could not be determined using 00395 // regular pap or boundary pap then we are unable to determine such value 00396 if ( dofManFlags.at(idofMan) == papStatus_littleNIPs ) { 00397 OOFEM_WARNING2("SPRNodalRecoveryModel::determinePatchAssemblyPoints - unable to determine dofMan %d\n", idofMan); 00398 //abort_flag = true; 00399 } 00400 } 00401 } 00402 } 00403 00404 if ( abort_flag ) { 00405 abort(); 00406 } 00407 00408 00409 count = 0; 00410 // count regular paps - those for which patch will be assembled 00411 for ( idofMan = 1; idofMan <= ndofMan; idofMan++ ) { 00412 if ( dofManFlags.at(idofMan) == papStatus_regular ) { 00413 count++; 00414 } 00415 } 00416 00417 pap.resize(count); 00418 count = 0; 00419 for ( idofMan = 1; idofMan <= ndofMan; idofMan++ ) { 00420 if ( dofManFlags.at(idofMan) == papStatus_regular ) { 00421 pap.at(++count) = idofMan; 00422 } 00423 } 00424 } 00425 00426 00427 void 00428 SPRNodalRecoveryModel :: initPatch(IntArray &patchElems, IntArray &dofManToDetermine, 00429 IntArray &pap, int papNumber, int ireg) 00430 { 00431 int nelem, ndofman, ielem, count, patchElements, i, j, includes, npap, ipap; 00432 const IntArray *papDofManConnectivity = domain->giveConnectivityTable()->giveDofManConnectivityArray(papNumber); 00433 std::list< int >dofManToDetermineList; 00434 std::list< int > :: iterator dofManToDetermineListIter; 00435 SPRNodalRecoveryModelInterface *interface; 00436 IntArray toDetermine, toDetermine2, elemPap, papInv; 00437 Element *element; 00438 00439 // looop over elements sharing dofManager with papNumber and 00440 // determine those in region in ireg 00441 // 00442 nelem = papDofManConnectivity->giveSize(); 00443 count = 0; 00444 for ( ielem = 1; ielem <= nelem; ielem++ ) { 00445 #ifdef __PARALLEL_MODE 00446 if ( domain->giveElement( papDofManConnectivity->at(ielem) )->giveParallelMode() != Element_local ) { 00447 continue; 00448 } 00449 00450 #endif 00451 if ( this->giveElementVirtualRegionNumber( papDofManConnectivity->at(ielem) ) == ireg ) { 00452 count++; 00453 } 00454 } 00455 00456 patchElems.resize(count); 00457 patchElements = 0; 00458 for ( ielem = 1; ielem <= nelem; ielem++ ) { 00459 #ifdef __PARALLEL_MODE 00460 if ( domain->giveElement( papDofManConnectivity->at(ielem) )->giveParallelMode() != Element_local ) { 00461 continue; 00462 } 00463 00464 #endif 00465 if ( this->giveElementVirtualRegionNumber( papDofManConnectivity->at(ielem) ) == ireg ) { 00466 patchElems.at(++patchElements) = papDofManConnectivity->at(ielem); 00467 } 00468 } 00469 00470 // Invert the pap array for faster access later 00471 ndofman = this->domain->giveNumberOfDofManagers(); 00472 papInv.resize(ndofman); 00473 papInv.zero(); 00474 for ( int i = 1; i <= pap.giveSize(); ++i ) { 00475 papInv.at( pap.at(i) ) = 1; 00476 } 00477 00478 // determine dofManagers which values will be determined by this patch 00479 // first add those required by elements participating in patch 00480 dofManToDetermine.resize(0); 00481 for ( ielem = 1; ielem <= patchElements; ielem++ ) { 00482 element = domain->giveElement( patchElems.at(ielem) ); 00483 00484 #ifdef __PARALLEL_MODE 00485 if ( element->giveParallelMode() != Element_local ) { 00486 continue; 00487 } 00488 00489 #endif 00490 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) ) { 00491 // add element reported dofMans for pap dofMan 00492 interface->SPRNodalRecoveryMI_giveDofMansDeterminedByPatch(toDetermine, papNumber); 00493 for ( i = 1; i <= toDetermine.giveSize(); i++ ) { 00494 includes = 0; 00495 // test if INCLUDED 00496 for ( dofManToDetermineListIter = dofManToDetermineList.begin(); 00497 dofManToDetermineListIter != dofManToDetermineList.end(); 00498 ++dofManToDetermineListIter ) { 00499 if ( * ( dofManToDetermineListIter ) == toDetermine.at(i) ) { 00500 includes = 1; 00501 } 00502 } 00503 00504 if ( !includes ) { 00505 dofManToDetermineList.push_back( toDetermine.at(i) ); 00506 } 00507 00508 // determine those dofManagers which are not reported by elements, 00509 // but their values shoud be determined from this patch 00510 // Example include pap DofMans with connectivity 1 00511 interface->SPRNodalRecoveryMI_giveSPRAssemblyPoints(elemPap); 00512 npap = elemPap.giveSize(); 00513 for ( ipap = 1; ipap <= npap; ipap++ ) { 00514 // test if element reported SPRAssembly point is not global assembly point 00515 // then determine this point from this patch 00516 if ( papInv.at( elemPap.at(ipap) ) == 0 ) { 00517 includes = 0; 00518 // test if INCLUDED 00519 for ( dofManToDetermineListIter = dofManToDetermineList.begin(); 00520 dofManToDetermineListIter != dofManToDetermineList.end(); 00521 ++dofManToDetermineListIter ) { 00522 if ( ( * dofManToDetermineListIter ) == elemPap.at(ipap) ) { 00523 includes = 1; 00524 } 00525 } 00526 00527 if ( !includes ) { 00528 dofManToDetermineList.push_back( elemPap.at(ipap) ); 00529 } 00530 00531 // add also all dofManagers which are reported by element for this Assembly node 00532 interface->SPRNodalRecoveryMI_giveDofMansDeterminedByPatch( toDetermine2, elemPap.at(ipap) ); 00533 for ( j = 1; j <= toDetermine2.giveSize(); j++ ) { 00534 includes = 0; 00535 // test if INCLUDED 00536 for ( dofManToDetermineListIter = dofManToDetermineList.begin(); 00537 dofManToDetermineListIter != dofManToDetermineList.end(); 00538 ++dofManToDetermineListIter ) { 00539 if ( * dofManToDetermineListIter == toDetermine2.at(j) ) { 00540 includes = 1; 00541 } 00542 } 00543 00544 if ( !includes ) { 00545 dofManToDetermineList.push_back( toDetermine2.at(j) ); 00546 } 00547 } 00548 } 00549 } 00550 } 00551 } 00552 } // end loop over patch elements 00553 00554 // transform set to dofManToDetermine array 00555 count = 0; 00556 for ( dofManToDetermineListIter = dofManToDetermineList.begin(); 00557 dofManToDetermineListIter != dofManToDetermineList.end(); 00558 ++dofManToDetermineListIter ) { 00559 count++; 00560 } 00561 00562 dofManToDetermine.resize(count); 00563 00564 count = 0; 00565 for ( dofManToDetermineListIter = dofManToDetermineList.begin(); 00566 dofManToDetermineListIter != dofManToDetermineList.end(); 00567 ++dofManToDetermineListIter ) { 00568 dofManToDetermine.at(++count) = * dofManToDetermineListIter; 00569 } 00570 } 00571 00572 00573 00574 void 00575 SPRNodalRecoveryModel :: computePatch(FloatMatrix &a, IntArray &patchElems, int papNumber, int regionValSize, 00576 SPRPatchType regType, InternalStateType type, TimeStep *tStep) 00577 { 00578 int nelem, nip, neq; 00579 Element *element; 00580 FloatArray ipVal, coords, P; 00581 FloatMatrix A, rhs; 00582 SPRNodalRecoveryModelInterface *interface; 00583 IntegrationRule *iRule; 00584 GaussPoint *gp; 00585 00586 neq = this->giveNumberOfUnknownPolynomialCoefficients(regType); 00587 a.resize(neq, regionValSize); 00588 a.zero(); 00589 rhs.resize(neq, regionValSize); 00590 rhs.zero(); 00591 A.resize(neq, neq); 00592 A.zero(); 00593 00594 // loop over elements in patch 00595 nelem = patchElems.giveSize(); 00596 for ( int ielem = 1; ielem <= nelem; ielem++ ) { 00597 element = domain->giveElement( patchElems.at(ielem) ); 00598 if ( ( interface = static_cast< SPRNodalRecoveryModelInterface * >( element->giveInterface(SPRNodalRecoveryModelInterfaceType) ) ) ) { 00599 iRule = element->giveDefaultIntegrationRulePtr(); 00600 nip = iRule->getNumberOfIntegrationPoints(); 00601 for ( int i = 0; i < nip; i++ ) { 00602 gp = iRule->getIntegrationPoint(i); 00603 if ( !element->giveIPValue(ipVal, gp, type, tStep) ) { 00604 ipVal.resize(regionValSize); 00605 ipVal.zero(); 00606 } 00607 00608 element->computeGlobalCoordinates( coords, * gp->giveLocalCoordinates() ); 00609 // compute ip contribution 00610 this->computePolynomialTerms(P, coords, regType); 00611 for ( int j = 1; j <= neq; j++ ) { 00612 for ( int k = 1; k <= regionValSize; k++ ) { 00613 rhs.at(j, k) += P.at(j) * ipVal.at(k); 00614 } 00615 00616 for ( int k = 1; k <= neq; k++ ) { 00617 A.at(j, k) += P.at(j) * P.at(k); 00618 } 00619 } 00620 } // end loop over nip 00621 00622 } 00623 } // end loop over elements 00624 00625 A.solveForRhs(rhs, a); 00626 } 00627 00628 void 00629 SPRNodalRecoveryModel :: determineValuesFromPatch(FloatArray &dofManValues, IntArray &dofManCount, 00630 IntArray ®ionNodalNumbers, IntArray &dofManToDetermine, 00631 FloatMatrix &a, int papNumber, int regionValSize, 00632 SPRPatchType type) 00633 { 00634 int eq, ndofMan = dofManToDetermine.giveSize(); 00635 FloatArray P, *coords, vals(regionValSize); 00636 int lneq = this->giveNumberOfUnknownPolynomialCoefficients(type); 00637 00638 for ( int dofMan = 1; dofMan <= ndofMan; dofMan++ ) { 00639 vals.zero(); 00640 coords = domain->giveNode( dofManToDetermine.at(dofMan) )->giveCoordinates(); 00641 this->computePolynomialTerms(P, * coords, type); 00642 for ( int i = 1; i <= regionValSize; i++ ) { 00643 for ( int j = 1; j <= lneq; j++ ) { 00644 vals.at(i) += P.at(j) * a.at(j, i); 00645 } 00646 } 00647 00648 // assemble values 00649 00650 eq = ( regionNodalNumbers.at( dofManToDetermine.at(dofMan) ) - 1 ) * regionValSize; 00651 for ( int i = 1; i <= regionValSize; i++ ) { 00652 dofManValues.at(eq + i) += vals.at(i); 00653 } 00654 00655 dofManCount.at( regionNodalNumbers.at( dofManToDetermine.at(dofMan) ) )++; 00656 } 00657 } 00658 00659 void 00660 SPRNodalRecoveryModel :: computePolynomialTerms(FloatArray &P, FloatArray &coords, SPRPatchType type) 00661 { 00662 if ( type == SPRPatchType_2dxy ) { 00663 P.resize(3); 00664 P.at(1) = 1.0; 00665 P.at(2) = coords.at(1); 00666 P.at(3) = coords.at(2); 00667 } else if ( type == SPRPatchType_3dBiLin ) { 00668 P.resize(4); 00669 P.at(1) = 1.0; 00670 P.at(2) = coords.at(1); 00671 P.at(3) = coords.at(2); 00672 P.at(4) = coords.at(3); 00673 } else if ( type == SPRPatchType_2dquadratic ) { 00674 P.resize(6); 00675 P.at(1) = 1.0; 00676 P.at(2) = coords.at(1); 00677 P.at(3) = coords.at(2); 00678 P.at(4) = coords.at(1) * coords.at(2); 00679 P.at(5) = coords.at(1) * coords.at(1); 00680 P.at(6) = coords.at(2) * coords.at(2); 00681 } else if ( type == SPRPatchType_3dBiQuadratic ) { 00682 P.resize(10); 00683 P.at(1) = 1.0; 00684 P.at(2) = coords.at(1); 00685 P.at(3) = coords.at(2); 00686 P.at(4) = coords.at(3); 00687 P.at(5) = coords.at(1) * coords.at(1); 00688 P.at(6) = coords.at(1) * coords.at(2); 00689 P.at(7) = coords.at(1) * coords.at(3); 00690 P.at(8) = coords.at(2) * coords.at(2); 00691 P.at(9) = coords.at(2) * coords.at(3); 00692 P.at(10) = coords.at(3) * coords.at(3); 00693 } else { 00694 OOFEM_ERROR("SPRNodalRecoveryModel::computePolynomialTerms - unknown regionType"); 00695 } 00696 } 00697 00698 int 00699 SPRNodalRecoveryModel :: giveNumberOfUnknownPolynomialCoefficients(SPRPatchType regType) 00700 { 00701 if ( regType == SPRPatchType_2dxy ) { 00702 return 3; 00703 } else if ( regType == SPRPatchType_3dBiLin ) { 00704 return 4; 00705 } else if ( regType == SPRPatchType_2dquadratic ) { 00706 return 6; 00707 } else if ( regType == SPRPatchType_3dBiQuadratic ) { 00708 return 10; 00709 } else { 00710 return 0; 00711 } 00712 } 00713 00714 00715 00716 #ifdef __PARALLEL_MODE 00717 00718 void 00719 SPRNodalRecoveryModel :: initCommMaps() 00720 { 00721 #ifdef __PARALLEL_MODE 00722 if ( initCommMap ) { 00723 EngngModel *emodel = domain->giveEngngModel(); 00724 ProblemCommunicatorMode commMode = emodel->giveProblemCommMode(); 00725 if ( commMode == ProblemCommMode__NODE_CUT ) { 00726 commBuff = new CommunicatorBuff(emodel->giveNumberOfProcesses(), CBT_dynamic); 00727 communicator = new ProblemCommunicator(emodel, commBuff, emodel->giveRank(), 00728 emodel->giveNumberOfProcesses(), 00729 commMode); 00730 communicator->setUpCommunicationMaps(domain->giveEngngModel(), true, true); 00731 OOFEM_LOG_INFO("SPRNodalRecoveryModel :: initCommMaps: initialized comm maps"); 00732 initCommMap = false; 00733 } else { 00734 OOFEM_ERROR("SPRNodalRecoveryModel :: initCommMaps: unsupported comm mode"); 00735 } 00736 } 00737 00738 #endif 00739 } 00740 00741 void 00742 SPRNodalRecoveryModel :: exchangeDofManValues(int ireg, FloatArray &dofManValues, IntArray &dofManPatchCount, 00743 IntArray ®ionNodalNumbers, int regionValSize) 00744 { 00745 EngngModel *emodel = domain->giveEngngModel(); 00746 ProblemCommunicatorMode commMode = emodel->giveProblemCommMode(); 00747 00748 if ( commMode == ProblemCommMode__NODE_CUT ) { 00749 parallelStruct ls( &dofManValues, &dofManPatchCount, ®ionNodalNumbers, regionValSize); 00750 00751 // exchange data for shared nodes 00752 communicator->packAllData(this, & ls, & SPRNodalRecoveryModel :: packSharedDofManData); 00753 communicator->initExchange(789 + ireg); 00754 communicator->unpackAllData(this, & ls, & SPRNodalRecoveryModel :: unpackSharedDofManData); 00755 communicator->finishExchange(); 00756 } else { 00757 OOFEM_ERROR("SPRNodalRecoveryModel :: exchangeDofManValues: Unsupported commMode"); 00758 } 00759 } 00760 00761 int 00762 SPRNodalRecoveryModel :: packSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) 00763 { 00764 int result = 1, i, j, indx, eq, size; 00765 ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); 00766 IntArray const *toSendMap = processComm.giveToSendMap(); 00767 00768 size = toSendMap->giveSize(); 00769 for ( i = 1; i <= size; i++ ) { 00770 // toSendMap contains all shared dofmans with remote partition 00771 // one has to check, if particular shared node value is available for given region 00772 indx = s->regionNodalNumbers->at( toSendMap->at(i) ); 00773 if ( indx && s->dofManPatchCount->at(indx) ) { 00774 // pack "1" to indicate that for given shared node this is a valid contribution 00775 result &= pcbuff->packInt(1); 00776 eq = ( indx - 1 ) * s->regionValSize; 00777 for ( j = 1; j <= s->regionValSize; j++ ) { 00778 result &= pcbuff->packDouble( s->dofManValues->at(eq + j) ); 00779 } 00780 } else { 00781 // ok shared node is not in active region (determined by s->regionNodalNumbers) 00782 result &= pcbuff->packInt(0); 00783 } 00784 } 00785 00786 return result; 00787 } 00788 00789 int 00790 SPRNodalRecoveryModel :: unpackSharedDofManData(parallelStruct *s, ProcessCommunicator &processComm) 00791 { 00792 int result = 1; 00793 int i, j, eq, indx, size, flag; 00794 IntArray const *toRecvMap = processComm.giveToRecvMap(); 00795 ProcessCommunicatorBuff *pcbuff = processComm.giveProcessCommunicatorBuff(); 00796 double value; 00797 00798 size = toRecvMap->giveSize(); 00799 for ( i = 1; i <= size; i++ ) { 00800 indx = s->regionNodalNumbers->at( toRecvMap->at(i) ); 00801 // toRecvMap contains all shared dofmans with remote partition 00802 // one has to check, if particular shared node received contribution is available for given region 00803 result &= pcbuff->unpackInt(flag); 00804 if ( flag ) { 00805 // "1" to indicates that for given shared node this is a valid contribution 00806 eq = ( indx - 1 ) * s->regionValSize; 00807 for ( j = 1; j <= s->regionValSize; j++ ) { 00808 result &= pcbuff->unpackDouble(value); 00809 if ( indx ) { 00810 s->dofManValues->at(eq + j) += value; 00811 } 00812 } 00813 00814 if ( indx ) { 00815 s->dofManPatchCount->at(indx)++; 00816 } 00817 } 00818 } 00819 00820 return result; 00821 } 00822 00823 #endif 00824 } // end namespace oofem