OOFEM  2.1
sprnodalrecoverymodel.C
Go to the documentation of this file.
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 &regionMap, IntArray &regionValSize,
00170                                        IntArray &regionTypes, 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 &regionNodalNumbers, 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 &regionNodalNumbers, 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, &regionNodalNumbers, 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

This page is part of the OOFEM documentation. Copyright (c) 2011 Borek Patzak
Project e-mail: info@oofem.org
Generated at Sun Mar 10 2013 18:16:56 for OOFEM by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2011