OOFEM  2.1
transportelement.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 "transportelement.h"
00036 #include "domain.h"
00037 #include "transportmaterial.h"
00038 #include "load.h"
00039 #include "boundaryload.h"
00040 #include "gausspnt.h"
00041 #include "gaussintegrationrule.h"
00042 #include "intarray.h"
00043 #include "flotarry.h"
00044 #include "flotmtrx.h"
00045 #include "verbose.h"
00046 #include "mathfem.h"
00047 #include "feinterpol.h"
00048 #include "feinterpol2d.h"
00049 #include "feinterpol3d.h"
00050 
00051 #ifdef __OOFEG
00052  #include "oofeggraphiccontext.h"
00053 #endif
00054 
00055 namespace oofem {
00056 TransportElement :: TransportElement(int n, Domain *aDomain, ElementMode em) :
00057     Element(n, aDomain)
00058 {
00059     emode = em;
00060 }
00061 
00062 
00063 TransportElement :: ~TransportElement()
00064 { }
00065 
00066 
00067 IRResultType
00068 TransportElement :: initializeFrom(InputRecord *ir)
00069 {
00070     //const char *__proc = "initializeFrom"; // Required by IR_GIVE_FIELD macro
00071     IRResultType result;                   // Required by IR_GIVE_FIELD macro
00072 
00073     result = Element :: initializeFrom(ir);
00074 
00075     return result;
00076 }
00077 
00078 
00079 void
00080 TransportElement :: giveElementDofIDMask(EquationID, IntArray &answer) const
00081 {
00082     if ( emode == HeatTransferEM ) {
00083         answer.setValues(1, T_f);
00084     } else if ( emode == HeatMass1TransferEM ) {
00085         answer.setValues(2, T_f, C_1);
00086     } else if ( emode == Mass1TransferEM ) {
00087         answer.setValues(1, C_1);
00088     } else {
00089         _error("Unknown ElementMode");
00090     }
00091 }
00092 
00093 
00094 void
00095 TransportElement :: giveDofManDofIDMask(int inode, EquationID eid, IntArray &answer) const
00096 {
00097     if ( eid == EID_ConservationEquation ) {
00098         if ( emode == HeatTransferEM ) {
00099             answer.setValues(1, T_f);
00100         } else if ( emode == HeatMass1TransferEM ) {
00101             answer.setValues(2, T_f, C_1);
00102         } else if ( emode == Mass1TransferEM ) {
00103             answer.setValues(1, C_1);
00104         } else {
00105             _error("Unknown ElementMode");
00106         }
00107     } else {
00108         answer.resize(0);
00109     }
00110 }
00111 
00112 
00113 void
00114 TransportElement :: giveCharacteristicMatrix(FloatMatrix &answer,
00115                                              CharType mtrx, TimeStep *tStep)
00116 //
00117 // returns characteristics matrix of receiver according to mtrx
00118 //
00119 {
00120     if ( mtrx == ConductivityMatrix ) {
00121         this->computeConductivityMatrix(answer, Conductivity, tStep);
00122     } else if ( mtrx == CapacityMatrix ) {
00123         this->computeCapacityMatrix(answer, tStep);
00124     } else if ( mtrx == LHSBCMatrix ) {
00125         this->computeBCMtrxAt(answer, tStep, VM_Total);
00126     } else if ( mtrx == IntSourceLHSMatrix ) {
00127         this->computeIntSourceLHSMatrix(answer, tStep);
00128     } else {
00129         _error2( "giveCharacteristicMatrix: Unknown Type of characteristic mtrx (%s)", __CharTypeToString(mtrx) );
00130     }
00131 }
00132 
00133 
00134 void
00135 TransportElement ::  giveCharacteristicVector(FloatArray &answer, CharType mtrx, ValueModeType mode,
00136                                               TimeStep *tStep)
00137 //
00138 // returns characteristics vector of receiver according to requested type
00139 //
00140 {
00141     if ( mtrx == ElementBCTransportVector ) {
00142         this->computeBCVectorAt(answer, tStep, mode);
00143     } else if ( mtrx == ElementInternalSourceVector ) {
00144         this->computeInternalSourceRhsVectorAt(answer, tStep, mode);
00145     } else {
00146         _error2( "giveCharacteristicVector: Unknown Type of characteristic mtrx (%s)",
00147                 __CharTypeToString(mtrx) );
00148     }
00149 }
00150 
00151 int
00152 TransportElement :: checkConsistency()
00153 //
00154 // check internal consistency
00155 // mainly tests, whether material and crossSection data
00156 // are safe for conversion to "Structural" versions
00157 //
00158 {
00159     int result = 1;
00160     if ( !dynamic_cast< TransportMaterial * >( giveMaterial() ) ) {
00161         _warning("checkConsistency : material without support for transport problems");
00162         result = 0;
00163     }
00164 
00165 #if 0
00166     if ( !this->giveCrossSection()->testCrossSectionExtension(CS_TransportCapability) ) {
00167         _warning("checkConsistency : cross-section without support for transport problems", 1);
00168         result = 0;
00169     }
00170 
00171 #endif
00172     return result;
00173 }
00174 
00175 void
00176 TransportElement :: printOutputAt(FILE *file, TimeStep *tStep)
00177 // Performs end-of-step operations.
00178 {
00179     Element :: printOutputAt(file, tStep);
00180 }
00181 
00182 void
00183 TransportElement :: computeCapacityMatrix(FloatMatrix &answer, TimeStep *tStep)
00184 {
00185     answer.resize( computeNumberOfDofs(EID_ConservationEquation), computeNumberOfDofs(EID_ConservationEquation) );
00186     answer.zero();
00187 
00188     if ( emode == HeatTransferEM || emode == Mass1TransferEM ) {
00189         this->computeCapacitySubMatrix(answer, Capacity, 0, tStep);
00190     } else if ( emode == HeatMass1TransferEM ) {
00191         FloatMatrix subAnswer;
00192         MatResponseMode rmode [ 2 ] = {
00193             Capacity_hh, Capacity_ww
00194         };
00195         //double coeff = 1.0; //this->giveMaterial()->give('d');
00196 
00197         for ( int i = 1; i <= 2; i++ ) {
00198             this->computeCapacitySubMatrix(subAnswer, rmode [ i - 1 ], 0, tStep);
00199             this->assembleLocalContribution(answer, subAnswer, 2, i, i);
00200         }
00201     } else {
00202         _error("Unknown ElementMode");
00203     }
00204 }
00205 
00206 void
00207 TransportElement :: computeConductivityMatrix(FloatMatrix &answer, MatResponseMode rMode, TimeStep *tStep)
00208 {
00209     answer.resize( computeNumberOfDofs(EID_ConservationEquation), computeNumberOfDofs(EID_ConservationEquation) );
00210     answer.zero();
00211     if ( emode == HeatTransferEM || emode == Mass1TransferEM ) {
00212         this->computeConductivitySubMatrix(answer, 2, 0, Conductivity_hh, tStep);
00213     } else if ( emode == HeatMass1TransferEM ) {
00214         FloatMatrix subAnswer;
00215         MatResponseMode rmode [ 2 ] [ 2 ] = { { Conductivity_hh, Conductivity_hw }, { Conductivity_wh, Conductivity_ww } };
00216 
00217         for ( int i = 1; i <= 2; i++ ) {
00218             for ( int j = 1; j <= 2; j++ ) {
00219                 this->computeConductivitySubMatrix(subAnswer, 2, 0, rmode [ i - 1 ] [ j - 1 ], tStep);
00220                 this->assembleLocalContribution(answer, subAnswer, 2, i, j);
00221             }
00222         }
00223     } else {
00224         _error("Unknown ElementMode");
00225     }
00226 }
00227 
00228 
00229 void
00230 TransportElement :: computeNAt(FloatArray &answer, const FloatArray &lcoord)
00231 {
00232     this->giveInterpolation()->evalN( answer, lcoord, FEIElementGeometryWrapper(this) );
00233 }
00234 
00235 
00236 void
00237 TransportElement :: computeNmatrixAt(FloatMatrix &answer, const FloatArray &lcoords)
00238 {
00239     FloatArray n;
00240     this->computeNAt(n, lcoords);
00241     int q = n.giveSize();
00242     if ( this->emode == HeatTransferEM  || this->emode == Mass1TransferEM ) {
00243         answer.resize(1, q);
00244         for ( int i = 1; i <= q; i++ ) {
00245             answer.at(1, i) = n.at(i);
00246         }
00247     } else {
00248         answer.resize(2, 2 * q);
00249         for ( int i = 0; i < 2; i++ ) {
00250             for ( int j = 0; j < q; j++ ) {
00251                 answer(i, j * 2 + i) = n(j);
00252             }
00253         }
00254     }
00255 }
00256 
00257 
00258 void
00259 TransportElement :: computeGradientMatrixAt(FloatMatrix &answer, GaussPoint *gp)
00260 {
00261     FloatMatrix dnx;
00262     this->giveInterpolation()->evaldNdx( dnx, * gp->giveCoordinates(), FEIElementGeometryWrapper(this) );
00264     answer.beTranspositionOf(dnx);
00265 }
00266 
00267 
00268 void
00269 TransportElement :: computeEgdeNAt(FloatArray &answer, int iedge, const FloatArray &lcoords)
00270 {
00271     FEInterpolation *interp = this->giveInterpolation();
00272     if ( dynamic_cast< FEInterpolation2d * >(interp) ) {
00273         dynamic_cast< FEInterpolation2d * >(interp)->edgeEvalN( answer, iedge, lcoords, FEIElementGeometryWrapper(this) );
00274     } else if ( dynamic_cast< FEInterpolation3d * >(interp) ) {
00275         dynamic_cast< FEInterpolation3d * >(interp)->edgeEvalN( answer, iedge, lcoords, FEIElementGeometryWrapper(this) );
00276     }
00277 }
00278 
00279 
00280 void
00281 TransportElement :: giveEdgeDofMapping(IntArray &answer, int iEdge)
00282 {
00283     FEInterpolation *interp = this->giveInterpolation();
00284     if ( dynamic_cast< FEInterpolation2d * >(interp) ) {
00285         dynamic_cast< FEInterpolation2d * >(interp)->computeLocalEdgeMapping(answer, iEdge);
00286     } else if ( dynamic_cast< FEInterpolation3d * >(interp) ) {
00287         dynamic_cast< FEInterpolation3d * >(interp)->computeLocalEdgeMapping(answer, iEdge);
00288     }
00289 }
00290 
00291 
00292 void
00293 TransportElement :: computeEdgeIpGlobalCoords(FloatArray &answer, const FloatArray &lcoords, int iEdge)
00294 {
00295     FEInterpolation *interp = this->giveInterpolation();
00296     if ( dynamic_cast< FEInterpolation2d * >(interp) ) {
00297         dynamic_cast< FEInterpolation3d * >(interp)->edgeLocal2global( answer, iEdge, lcoords, FEIElementGeometryWrapper(this) );
00298     } else if ( dynamic_cast< FEInterpolation3d * >(interp) ) {
00299         dynamic_cast< FEInterpolation3d * >(interp)->edgeLocal2global( answer, iEdge, lcoords, FEIElementGeometryWrapper(this) );
00300     }
00301 }
00302 
00303 void
00304 TransportElement :: computeSurfaceNAt(FloatArray &answer, int iSurf, const FloatArray &lcoord)
00305 {
00306     FEInterpolation *interp = this->giveInterpolation();
00307     if ( dynamic_cast< FEInterpolation3d * >(interp) ) {
00308         dynamic_cast< FEInterpolation3d * >(interp)->surfaceEvalN( answer, iSurf, lcoord, FEIElementGeometryWrapper(this) );
00309     }
00310 }
00311 
00312 void
00313 TransportElement :: giveSurfaceDofMapping(IntArray &answer, int iSurf)
00314 {
00315     FEInterpolation *interp = this->giveInterpolation();
00316     if ( dynamic_cast< FEInterpolation3d * >(interp) ) {
00317         dynamic_cast< FEInterpolation3d * >(interp)->computeLocalSurfaceMapping(answer, iSurf);
00318     }
00319 }
00320 
00321 void
00322 TransportElement :: computeSurfIpGlobalCoords(FloatArray &answer, const FloatArray &lcoord, int iSurf)
00323 {
00324     FEInterpolation *interp = this->giveInterpolation();
00325     if ( dynamic_cast< FEInterpolation3d * >(interp) ) {
00326         dynamic_cast< FEInterpolation3d * >(interp)->edgeLocal2global( answer, iSurf, lcoord, FEIElementGeometryWrapper(this) );
00327     }
00328 }
00329 
00330 int
00331 TransportElement :: giveApproxOrder(int unknownIndx)
00332 {
00333     return this->giveInterpolation()->giveInterpolationOrder();
00334 }
00335 
00336 void
00337 TransportElement :: computeCapacitySubMatrix(FloatMatrix &answer, MatResponseMode rmode, int iri, TimeStep *tStep)
00338 {
00339     double dV, c;
00340     FloatArray n;
00341     GaussPoint *gp;
00342     IntegrationRule *iRule = integrationRulesArray [ iri ];
00343     TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() );
00344 
00345     answer.beEmptyMtrx();
00346     for ( int i = 0; i < iRule->getNumberOfIntegrationPoints(); i++ ) {
00347         gp = iRule->getIntegrationPoint(i);
00348         this->computeNAt( n, * gp->giveCoordinates() );
00349         // ask for capacity coefficient. In basic units [J/K/m3]
00350         c = mat->giveCharacteristicValue(rmode, gp, tStep);
00351         dV = this->computeVolumeAround(gp);
00352         answer.plusDyadSymmUpper(n, n, dV * c);
00353     }
00354 
00355     answer.symmetrized();
00356 }
00357 
00358 void
00359 TransportElement :: computeConductivitySubMatrix(FloatMatrix &answer, int nsd, int iri, MatResponseMode rmode, TimeStep *tStep)
00360 {
00361     double dV;
00362     FloatMatrix b, d, db;
00363     GaussPoint *gp;
00364     IntegrationRule *iRule = integrationRulesArray [ iri ];
00365 
00366     answer.resize( this->giveNumberOfDofManagers(), this->giveNumberOfDofManagers() );
00367     answer.zero();
00368     for ( int i = 0; i < iRule->getNumberOfIntegrationPoints(); i++ ) {
00369         gp = iRule->getIntegrationPoint(i);
00370         this->computeConstitutiveMatrixAt(d, rmode, gp, tStep);
00371         this->computeGradientMatrixAt(b, gp);
00372         dV = this->computeVolumeAround(gp);
00373 
00374         db.beProductOf(d, b);
00375         answer.plusProductSymmUpper(b, db, dV);
00376     }
00377 
00378     answer.symmetrized();
00379 }
00380 
00381 void
00382 TransportElement :: computeInternalSourceRhsSubVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode, int indx)
00383 {
00384     // Computes numerically the generator Rhs vector of the receiver due to the generator
00385     //  at tStep.
00386     // // load is first transformed to local cs.
00387     // // load vector is then transformed to coordinate system in each node.
00388     // // (should be global coordinate system, but there may be defined
00389     // //  different coordinate system in each node)
00390     int k, nLoads;
00391     double dV;
00392     bcGeomType ltype;
00393     Load *load;
00394     IntegrationRule *iRule = integrationRulesArray [ giveDefaultIntegrationRule() ];
00395     TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() );
00396     GaussPoint *gp;
00397 
00398 
00399     FloatArray val, helpLoadVector, globalIPcoords, n;
00400     answer.resize(0);
00401 
00402     nLoads = this->giveBodyLoadArray()->giveSize();
00403     for ( int i = 1; i <= nLoads; i++ ) {
00404         k = bodyLoadArray.at(i);
00405         load = domain->giveLoad(k);
00406         ltype = load->giveBCGeoType();
00407         if ( ltype == BodyLoadBGT ) {
00408             for ( int igp = 0; igp < iRule->getNumberOfIntegrationPoints(); igp++ ) {
00409                 gp  = iRule->getIntegrationPoint(igp);
00410                 this->computeNAt( n, * gp->giveCoordinates() );
00411                 dV  = this->computeVolumeAround(gp);
00412                 this->computeGlobalCoordinates( globalIPcoords, * gp->giveCoordinates() );
00413                 load->computeValueAt(val, tStep, globalIPcoords, mode);
00414 
00415                 helpLoadVector.add(val.at(indx) * dV, n);
00416             }
00417 
00418             answer.add(helpLoadVector);
00419         }
00420     }
00421 
00422     // add internal source produced by material (if any)
00423     if ( mat->hasInternalSource() ) {
00424         for ( int igp = 0; igp < iRule->getNumberOfIntegrationPoints(); igp++ ) {
00425             gp  = iRule->getIntegrationPoint(igp);
00426             this->computeNAt( n, * gp->giveCoordinates() );
00427             dV  = this->computeVolumeAround(gp);
00428             mat->computeInternalSourceVector(val, gp, tStep, mode);
00429 
00430             helpLoadVector.add(val.at(indx) * dV, n);
00431         }
00432 
00433         answer.add(helpLoadVector);
00434     }
00435 }
00436 
00437 
00438 void
00439 TransportElement :: computeInternalSourceRhsVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
00440 {
00441     if ( emode == HeatTransferEM || emode == Mass1TransferEM ) {
00442         this->computeInternalSourceRhsSubVectorAt(answer, tStep, mode, 1);
00443     } else if ( emode == HeatMass1TransferEM ) {
00444         FloatArray subAnswer;
00445 
00446         for ( int i = 1; i <= 2; i++ ) {
00447             this->computeInternalSourceRhsSubVectorAt(subAnswer, tStep, mode, i);
00448             if ( subAnswer.isNotEmpty() ) {
00449                 if ( answer.isEmpty() ) {
00450                     answer.resize( 2 * subAnswer.giveSize() );
00451                     answer.zero();
00452                 }
00453 
00454                 this->assembleLocalContribution(answer, subAnswer, 2, i);
00455             }
00456         }
00457     } else {
00458         _error("Unknown ElementMode");
00459     }
00460 }
00461 
00462 
00463 void
00464 TransportElement :: computeIntSourceLHSMatrix(FloatMatrix &answer, TimeStep *tStep)
00465 {
00466     TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() );
00467     if ( mat->hasInternalSource() ) {
00468         answer.resize( computeNumberOfDofs(EID_ConservationEquation), computeNumberOfDofs(EID_ConservationEquation) );
00469         answer.zero();
00470 
00471         if ( emode == HeatTransferEM || emode == Mass1TransferEM ) {
00472             this->computeIntSourceLHSSubMatrix(answer, IntSource, 0, tStep);
00473         } else if ( emode == HeatMass1TransferEM ) {
00474             FloatMatrix subAnswer;
00475             MatResponseMode rmode [ 2 ] = {
00476                 IntSource_hh, IntSource_ww
00477             };
00478             //double coeff = 1.0; //this->giveMaterial()->give('d');
00479 
00480             for ( int i = 1; i <= 2; i++ ) {
00481                 this->computeIntSourceLHSSubMatrix(subAnswer, rmode [ i - 1 ], 0, tStep);
00482                 this->assembleLocalContribution(answer, subAnswer, 2, i, i);
00483             }
00484         } else {
00485             _error("Unknown ElementMode");
00486         }
00487     } else {
00488         answer.beEmptyMtrx();
00489     }
00490 }
00491 
00492 void
00493 TransportElement :: computeIntSourceLHSSubMatrix(FloatMatrix &answer, MatResponseMode rmode, int iri, TimeStep *tStep)
00494 // computes LHS matrix due to material internal source (dHeat/dTemperature, dWaterSource/dw)
00495 // IntSource - Heat transfer
00496 // IntSource_hh - HeMo heat source
00497 // IntSource_ww - HeMo water content source
00498 // hw, wh is not used now
00499 {
00500     double dV, c;
00501     FloatArray n;
00502     GaussPoint *gp;
00503     IntegrationRule *iRule = integrationRulesArray [ iri ];
00504     TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() );
00505 
00506     answer.beEmptyMtrx();
00507     for ( int i = 0; i < iRule->getNumberOfIntegrationPoints(); i++ ) {
00508         gp = iRule->getIntegrationPoint(i);
00509         this->computeNAt( n, * gp->giveCoordinates() );
00510         // ask for coefficient from material
00511         c = mat->giveCharacteristicValue(rmode, gp, tStep);
00512         dV = this->computeVolumeAround(gp);
00513         answer.plusDyadSymmUpper(n, n, dV * c);
00514     }
00515 
00516     answer.symmetrized();
00517 }
00518 
00519 
00520 void
00521 TransportElement :: computeConstitutiveMatrixAt(FloatMatrix &answer,
00522                                                 MatResponseMode rMode, GaussPoint *gp,
00523                                                 TimeStep *tStep)
00524 {
00525     static_cast< TransportMaterial * >( this->giveMaterial() )->giveCharacteristicMatrix(answer, FullForm, rMode, gp, tStep);
00526 }
00527 
00528 
00529 void
00530 TransportElement :: computeBCVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode)
00531 {
00532     answer.resize( computeNumberOfDofs(EID_ConservationEquation) );
00533     answer.zero();
00534 
00535     if ( emode == HeatTransferEM || emode == Mass1TransferEM ) {
00536         this->computeBCSubVectorAt(answer, tStep, mode, 1);
00537     } else if ( emode == HeatMass1TransferEM ) {
00538         FloatArray subAnswer;
00539 
00540         for ( int i = 1; i <= 2; i++ ) {
00541             this->computeBCSubVectorAt(subAnswer, tStep, mode, i);
00542             this->assembleLocalContribution(answer, subAnswer, 2, i);
00543         }
00544     } else {
00545         _error("Unknown ElementMode");
00546     }
00547 }
00548 
00549 void
00550 TransportElement :: computeBCMtrxAt(FloatMatrix &answer, TimeStep *tStep, ValueModeType mode)
00551 {
00552     int ndofs = computeNumberOfDofs(EID_ConservationEquation);
00553     answer.resize(ndofs, ndofs);
00554     answer.zero();
00555 
00556     if ( emode == HeatTransferEM || emode == Mass1TransferEM ) {
00557         this->computeBCSubMtrxAt(answer, tStep, mode, 1);
00558     } else if ( emode == HeatMass1TransferEM ) {
00559         FloatMatrix subAnswer;
00560 
00561         for ( int i = 1; i <= 2; i++ ) {
00562             this->computeBCSubMtrxAt(subAnswer, tStep, mode, i);
00563             if ( subAnswer.isNotEmpty() ) {
00564                 this->assembleLocalContribution(answer, subAnswer, 2, i, i);
00565             }
00566         }
00567     } else {
00568         _error("Unknown ElementMode");
00569     }
00570 }
00571 
00572 
00573 void
00574 TransportElement :: computeBCSubVectorAt(FloatArray &answer, TimeStep *tStep, ValueModeType mode, int indx)
00575 {
00576     int n, id;
00577     Load *load;
00578     bcGeomType ltype;
00579     FloatArray vec;
00580 
00581     answer.resize( this->giveNumberOfDofManagers() );
00582     answer.zero();
00583 
00584     // loop over boundary load array
00585     int nLoads = this->giveBoundaryLoadArray()->giveSize() / 2;
00586     for ( int i = 1; i <= nLoads; i++ ) {
00587         n = boundaryLoadArray.at(1 + ( i - 1 ) * 2);
00588         id = boundaryLoadArray.at(i * 2);
00589         load = domain->giveLoad(n);
00590         ltype = load->giveBCGeoType();
00591         if ( ltype == EdgeLoadBGT ) {
00592             this->computeEdgeBCSubVectorAt(vec, load, id, tStep, mode, indx);
00593         } else if ( ltype == SurfaceLoadBGT ) {
00594             this->computeSurfaceBCSubVectorAt(vec, load, id, tStep, mode, indx);
00595         } else {
00596             _error("computeBCSubVectorAt : unsupported bc type encountered");
00597         }
00598 
00599         answer.add(vec);
00600     }
00601 
00602     // end loop over applied bc
00603 }
00604 
00605 void
00606 TransportElement :: computeEdgeBCSubVectorAt(FloatArray &answer, Load *load, int iEdge,
00607                                              TimeStep *tStep, ValueModeType mode, int indx)
00608 {
00609     int approxOrder, numberOfEdgeIPs;
00610 
00611     answer.resize( this->giveNumberOfDofManagers() );
00612     answer.zero();
00613 
00614     if ( ( load->giveType() == TransmissionBC ) || ( load->giveType() == ConvectionBC ) ) {
00615         BoundaryLoad *edgeLoad = static_cast< BoundaryLoad * >(load);
00616         if ( edgeLoad->isDofExcluded(indx) || !edgeLoad->isImposed(tStep) ) {
00617             return;
00618         }
00619 
00620 
00621         approxOrder = edgeLoad->giveApproxOrder() + this->giveApproxOrder(indx);
00622         numberOfEdgeIPs = ( int ) ceil( ( approxOrder + 1. ) / 2. );
00623         GaussIntegrationRule iRule(1, this, 1, 1);
00624         iRule.setUpIntegrationPoints(_Line, numberOfEdgeIPs, _Unknown);
00625         GaussPoint *gp;
00626         FloatArray reducedAnswer, val, ntf, n;
00627         IntArray mask;
00628         double dV, coeff = 1.0;
00629 
00630         if ( load->giveType() == TransmissionBC ) {
00631             coeff = -1.0;
00632         } else {
00633             coeff = edgeLoad->giveProperty('a');
00634         }
00635 
00636         for ( int i = 0; i < iRule.getNumberOfIntegrationPoints(); i++ ) {
00637             gp  = iRule.getIntegrationPoint(i);
00638             FloatArray *lcoords = gp->giveCoordinates();
00639             this->computeEgdeNAt(n, iEdge, * lcoords);
00640             dV = this->computeEdgeVolumeAround(gp, iEdge);
00641 
00642             if ( edgeLoad->giveFormulationType() == BoundaryLoad :: BL_EntityFormulation ) {
00643                 edgeLoad->computeValueAt(val, tStep, * lcoords, mode);
00644             } else {
00645                 FloatArray globalIPcoords;
00646                 this->computeEdgeIpGlobalCoords(globalIPcoords, * lcoords, iEdge);
00647                 edgeLoad->computeValueAt(val, tStep, globalIPcoords, mode);
00648             }
00649 
00650             reducedAnswer.add(val.at(indx) * coeff * dV, n);
00651         }
00652 
00653         this->giveEdgeDofMapping(mask, iEdge);
00654         answer.assemble(reducedAnswer, mask);
00655     } else {
00656         _error("computeBCSubVectorAt : unsupported bc type encountered");
00657     }
00658 }
00659 
00660 void
00661 TransportElement :: computeSurfaceBCSubVectorAt(FloatArray &answer, Load *load,
00662                                                 int iSurf, TimeStep *tStep, ValueModeType mode, int indx)
00663 {
00664     int approxOrder;
00665     double dV, coeff = 1.0;
00666 
00667     if ( !this->testElementExtension(Element_SurfaceLoadSupport) ) {
00668         _error("computeSurfaceBCSubVectorAt : no surface load support");
00669     }
00670 
00671     BoundaryLoad *surfLoad = dynamic_cast< BoundaryLoad * >( load );
00672     if ( surfLoad ) {
00673         IntegrationRule *iRule;
00674         GaussPoint *gp;
00675         FloatArray reducedAnswer, val, globalIPcoords, n;
00676         IntArray mask;
00677 
00678         answer.resize( this->giveNumberOfDofManagers() );
00679         answer.zero();
00680 
00681         if ( surfLoad->isDofExcluded(indx) || !surfLoad->isImposed(tStep) ) {
00682             return;
00683         }
00684 
00685         if ( load->giveType() == TransmissionBC ) {
00686             coeff = -1.0;
00687         } else {
00688             coeff = surfLoad->giveProperty('a');
00689         }
00690 
00691         approxOrder = surfLoad->giveApproxOrder() + this->giveApproxOrder(indx);
00692 
00693         iRule = this->GetSurfaceIntegrationRule(approxOrder);
00694         for ( int i = 0; i < iRule->getNumberOfIntegrationPoints(); i++ ) {
00695             gp = iRule->getIntegrationPoint(i);
00696             this->computeSurfaceNAt( n, iSurf, * gp->giveCoordinates() );
00697             dV = this->computeSurfaceVolumeAround(gp, iSurf);
00698 
00699             if ( surfLoad->giveFormulationType() == BoundaryLoad :: BL_EntityFormulation ) {
00700                 surfLoad->computeValueAt(val, tStep, * gp->giveCoordinates(), mode);
00701             } else {
00702                 this->computeSurfIpGlobalCoords(globalIPcoords, * gp->giveCoordinates(), iSurf);
00703                 surfLoad->computeValueAt(val, tStep, globalIPcoords, mode);
00704             }
00705 
00706             reducedAnswer.add(val.at(indx) * coeff * dV, n);
00707         }
00708 
00709         this->giveSurfaceDofMapping(mask, iSurf);
00710         answer.assemble(reducedAnswer, mask);
00711 
00712         delete iRule;
00713     } else {
00714         _error("computeSurfaceBCSubVectorAt : unsupported bc type encountered");
00715     }
00716 }
00717 
00718 
00719 
00720 
00721 void
00722 TransportElement :: computeBCSubMtrxAt(FloatMatrix &answer, TimeStep *tStep, ValueModeType mode, int indx)
00723 {
00724     int k, id, defined = 0;
00725     GeneralBoundaryCondition *load;
00726     double dV;
00727     bcGeomType ltype;
00728 
00729     answer.resize( this->giveNumberOfDofManagers(), this->giveNumberOfDofManagers() );
00730     answer.zero();
00731 
00732     // loop over boundary load array
00733     int nLoads = this->giveBoundaryLoadArray()->giveSize() / 2;
00734     for ( int i = 1; i <= nLoads; i++ ) {
00735         k = boundaryLoadArray.at(1 + ( i - 1 ) * 2);
00736         id = boundaryLoadArray.at(i * 2);
00737         load = domain->giveLoad(k);
00738         if ( load->giveType() == ConvectionBC ) {
00739             ltype = load->giveBCGeoType();
00740             if ( ltype == EdgeLoadBGT ) {
00741                 BoundaryLoad *edgeLoad = static_cast< BoundaryLoad * >( load );
00742                 if ( edgeLoad->isDofExcluded(indx) || !edgeLoad->isImposed(tStep) ) {
00743                     continue;
00744                 }
00745 
00746                 defined = 1;
00747                 int approxOrder = 2 * this->giveApproxOrder(indx);
00748                 int numberOfEdgeIPs = ( int ) ceil( ( approxOrder + 1. ) / 2. );
00749                 GaussIntegrationRule iRule(1, this, 1, 1);
00750                 iRule.setUpIntegrationPoints(_Line, numberOfEdgeIPs, _Unknown);
00751                 GaussPoint *gp;
00752                 FloatArray val, n;
00753                 IntArray mask;
00754                 FloatMatrix subAnswer;
00755 
00756                 for ( int igp = 0; igp < iRule.getNumberOfIntegrationPoints(); igp++ ) {
00757                     gp = iRule.getIntegrationPoint(igp);
00758                     this->computeEgdeNAt( n, id, * gp->giveCoordinates() );
00759                     dV = this->computeEdgeVolumeAround(gp, id);
00760                     subAnswer.plusDyadSymmUpper( n, n, dV * edgeLoad->giveProperty('a') );
00761                 }
00762 
00763                 subAnswer.symmetrized();
00764                 this->giveEdgeDofMapping(mask, id);
00765                 answer.assemble(subAnswer, mask);
00766             } else if ( ltype == SurfaceLoadBGT ) {
00767                 IntegrationRule *iRule;
00768                 GaussPoint *gp;
00769                 FloatArray val, n;
00770                 IntArray mask;
00771                 FloatMatrix subAnswer;
00772 
00773                 BoundaryLoad *surfLoad = static_cast< BoundaryLoad * >( load );
00774                 if ( surfLoad->isDofExcluded(indx) || !surfLoad->isImposed(tStep) ) {
00775                     continue;
00776                 }
00777 
00778                 defined = 1;
00779                 int approxOrder = 2 * this->giveApproxOrder(indx);
00780                 iRule = this->GetSurfaceIntegrationRule(approxOrder);
00781 
00782                 for ( int igp = 0; igp < iRule->getNumberOfIntegrationPoints(); igp++ ) {
00783                     gp  = iRule->getIntegrationPoint(igp);
00784                     this->computeSurfaceNAt( n, id, * gp->giveCoordinates() );
00785                     dV  = this->computeSurfaceVolumeAround(gp, id);
00786                     subAnswer.plusDyadSymmUpper( n, n, dV * surfLoad->giveProperty('a') );
00787                 }
00788 
00789                 delete iRule;
00790                 subAnswer.symmetrized();
00791                 this->giveSurfaceDofMapping(mask, id);
00792                 answer.assemble(subAnswer, mask);
00793             } else {
00794                 _error("computeBCSubMtrxAt : unsupported bc type encountered");
00795             }
00796         }
00797     }
00798 
00799     // end loop over applied bc
00800 
00801     if ( !defined ) {
00802         answer.resize(0, 0);
00803     }
00804 }
00805 
00806 
00807 void
00808 TransportElement :: assembleLocalContribution(FloatMatrix &answer, FloatMatrix &src,
00809                                               int ndofs, int rdof, int cdof)
00810 {
00811     int ti, tj;
00812     int nnodes = this->giveNumberOfDofManagers();
00813 
00814     for ( int i = 1; i <= nnodes; i++ ) {
00815         ti = ( i - 1 ) * ndofs + rdof;
00816         for ( int j = 1; j <= nnodes; j++ ) {
00817             tj = ( j - 1 ) * ndofs + cdof;
00818             answer.at(ti, tj) += src.at(i, j);
00819         }
00820     }
00821 }
00822 
00823 
00824 void
00825 TransportElement :: assembleLocalContribution(FloatArray &answer, FloatArray &src,
00826                                               int ndofs, int rdof)
00827 {
00828     int ti;
00829     int nnodes = this->giveNumberOfDofManagers();
00830 
00831     for ( int i = 1; i <= nnodes; i++ ) {
00832         ti = ( i - 1 ) * ndofs + rdof;
00833         answer.at(ti) += src.at(i);
00834     }
00835 }
00836 
00837 void
00838 TransportElement :: computeFlow(FloatArray &answer, GaussPoint *gp, TimeStep *tStep)
00839 {
00840     FloatArray r, br;
00841     FloatMatrix b, d;
00842 
00843     this->computeVectorOf(EID_ConservationEquation, VM_Total, tStep, r);
00844     this->computeGradientMatrixAt(b, gp);
00845 
00846     if ( emode == HeatTransferEM ||  emode == Mass1TransferEM ) {
00847         this->computeConstitutiveMatrixAt(d, Conductivity_hh, gp, tStep);
00848         br.beProductOf(b, r);
00849         answer.beProductOf(d, br);
00850     } else if ( emode == HeatMass1TransferEM ) {
00851         FloatArray r_h, r_w;
00852         FloatMatrix b_tot, d_hh, d_hw, d_wh, d_ww;
00853         r_h.resize(r.giveSize() / 2);
00854         r_h.zero();
00855         r_w.resize(r.giveSize() / 2);
00856         r_w.zero();
00857 
00858         this->computeConstitutiveMatrixAt(d_hh, Conductivity_hh, gp, tStep);
00859         this->computeConstitutiveMatrixAt(d_hw, Conductivity_hw, gp, tStep);
00860         this->computeConstitutiveMatrixAt(d_wh, Conductivity_wh, gp, tStep);
00861         this->computeConstitutiveMatrixAt(d_ww, Conductivity_ww, gp, tStep);
00862 
00863         b_tot.resize( 2 * b.giveNumberOfRows(), 2 * b.giveNumberOfColumns() );
00864         b_tot.setSubMatrix(b, 1, 1);
00865         b_tot.setSubMatrix(b, b.giveNumberOfRows() + 1, b.giveNumberOfColumns() + 1);
00866         br.beProductOf(b_tot, r);
00867 
00868         d.resize( 2 * d_hh.giveNumberOfRows(), 2 * d_hh.giveNumberOfColumns() );
00869         d.setSubMatrix(d_hh, 1, 1);
00870         d.setSubMatrix(d_hw, 1, d_hh.giveNumberOfColumns() + 1);
00871         d.setSubMatrix(d_wh, d_hh.giveNumberOfRows() + 1, 1);
00872         d.setSubMatrix(d_ww, d_hh.giveNumberOfRows() + 1, d_wh.giveNumberOfColumns() + 1);
00873 
00874         answer.beProductOf(d, br);
00875     } else {
00876         OOFEM_ERROR1("Unknown element mode");
00877     }
00878 
00879     answer.negated();
00880 
00881     if ( !isActivated(tStep) ) {
00882         answer.zero();
00883     }
00884 }
00885 
00886 
00887 void
00888 TransportElement :: updateInternalState(TimeStep *tStep)
00889 // Updates the receiver at the end of a solution step
00890 {
00891     IntegrationRule *iRule;
00892     FloatArray stateVector, r;
00893     FloatArray gradient, flux;
00894     FloatMatrix n, B;
00895     TransportMaterial *mat = static_cast< TransportMaterial * >( this->giveMaterial() );
00896     GaussPoint *gp;
00897 
00898     this->computeVectorOf(EID_ConservationEquation, VM_Total, tStep, r);
00899     // force updating ip values
00900     for ( int i = 0; i < numberOfIntegrationRules; i++ ) {
00901         iRule = integrationRulesArray [ i ];
00902         for ( int j = 0; j < iRule->getNumberOfIntegrationPoints(); j++ ) {
00903             gp = iRule->getIntegrationPoint(j);
00904 
00906             this->computeNmatrixAt( n, * gp->giveCoordinates() );
00907             stateVector.beProductOf(n, r);
00908             mat->updateInternalState(stateVector, gp, tStep);
00909 
00911 #if 0
00912             this->computeGradientMatrixAt( B, * gp->giveCoordinates() );
00913             gradient.beProductOf(B, r);
00914             mat->giveFluxVector(flux, gp, gradient, tStep);
00915 #endif
00916         }
00917     }
00918 }
00919 
00920 int
00921 TransportElement :: EIPrimaryFieldI_evaluateFieldVectorAt(FloatArray &answer, PrimaryField &pf,
00922                                                           FloatArray &coords, IntArray &dofId, ValueModeType mode,
00923                                                           TimeStep *tStep)
00924 {
00925     int indx;
00926     FloatArray elemvector, f, lc;
00927     FloatMatrix n;
00928     IntArray elemdofs;
00929     // determine element dof ids
00930     this->giveElementDofIDMask(pf.giveEquationID(), elemdofs);
00931     // first evaluate element unknown vector
00932     this->computeVectorOf(pf, mode, tStep, elemvector);
00933     // determine corresponding local coordinates
00934     if ( this->computeLocalCoordinates(lc, coords) ) {
00935         // compute interpolation matrix
00936         this->computeNmatrixAt(n, lc);
00937         // compute answer
00938         answer.resize( dofId.giveSize() );
00939         for ( int i = 1; i <= dofId.giveSize(); i++ ) {
00940             if ( ( indx = elemdofs.findFirstIndexOf( dofId.at(i) ) ) ) {
00941                 double sum = 0.0;
00942                 for ( int j = 1; j <= elemvector.giveSize(); j++ ) {
00943                     sum += n.at(indx, j) * elemvector.at(j);
00944                 }
00945 
00946                 answer.at(i) = sum;
00947             } else {
00948                 //_error("EIPrimaryFieldI_evaluateFieldVectorAt: unknown dof id encountered");
00949                 answer.at(i) = 0.0;
00950             }
00951         }
00952 
00953         return 0; // ok
00954     } else {
00955         _error("EIPrimaryFieldI_evaluateFieldVectorAt: target point not in receiver volume");
00956         return 1; // failed
00957     }
00958 }
00959 
00960 
00961 #ifdef __OOFEG
00962 int
00963 TransportElement :: giveInternalStateAtNode(FloatArray &answer, InternalStateType type, InternalStateMode mode,
00964                                             int node, TimeStep *tStep)
00965 {
00966     Node *n = this->giveNode(node);
00967     if ( type == IST_Temperature ) {
00968         int dofindx;
00969         if ( ( dofindx = n->findDofWithDofId(T_f) ) ) {
00970             answer.resize(1);
00971             answer.at(1) = n->giveDof(dofindx)->giveUnknown(EID_ConservationEquation, VM_Total, tStep);
00972             return 1;
00973         } else {
00974             return 0;
00975         }
00976     } else if ( type == IST_MassConcentration_1 ) {
00977         int dofindx;
00978         if ( ( dofindx = n->findDofWithDofId(C_1) ) ) {
00979             answer.resize(1);
00980             answer.at(1) = n->giveDof(dofindx)->giveUnknown(EID_ConservationEquation, VM_Total, tStep);
00981             return 1;
00982         } else {
00983             return 0;
00984         }
00985     } else {
00986         return Element :: giveInternalStateAtNode(answer, type, mode, node, tStep);
00987     }
00988 }
00989 
00990 #endif
00991 
00992 int
00993 TransportElement :: giveIntVarCompFullIndx(IntArray &answer, InternalStateType type)
00994 {
00995     if ( ( type == IST_Temperature ) || ( type == IST_MassConcentration_1 ) ) {
00996         answer.resize(1);
00997         answer.at(1) = 1;
00998         return 1;
00999     } else {
01000         return Element :: giveIntVarCompFullIndx(answer, type);
01001     }
01002 }
01003 } // 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:57 for OOFEM by doxygen 1.7.6.1 written by Dimitri van Heesch, © 1997-2011