|
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 "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