00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef CONVECTION_HPP
00022 #define CONVECTION_HPP
00023
00024 #include <ScalarFunctionBase.hpp>
00025 #include <FieldOfScalarFunction.hpp>
00026
00027 #include <Structured3DMesh.hpp>
00028 #include <MeshOfTetrahedra.hpp>
00029
00030 #include <ConnectivityBuilder.hpp>
00031
00032 #include <ConformTransformation.hpp>
00033
00034 #include <limits>
00046 template <typename MeshType>
00047 struct Convection
00048 : public ScalarFunctionBase
00049 {
00050 };
00051
00060 template <>
00061 class Convection<Structured3DMesh>
00062 : public ScalarFunctionBase
00063 {
00064 private:
00072 std::ostream& __put(std::ostream& os) const
00073 {
00074 os << "convect(" << __u << ","
00075 << __deltaT << ',' << __phi << ')';
00076 return os;
00077 }
00078
00080 const real_t __deltaT;
00081
00083 const Structured3DMesh& __mesh;
00084
00086 const FieldOfScalarFunction& __u;
00087
00089 const ScalarFunctionBase& __phi;
00090
00096 Convection(const Convection<Structured3DMesh>& C);
00097
00098 public:
00100 real_t operator()(const TinyVector<3>& X) const
00101 {
00102 Structured3DMesh::const_iterator h = __mesh.find(X[0], X[1], X[2]);
00103 if (h.end()) {
00104 return 0;
00105 }
00106
00107 const ScalarFunctionBase& u0 = *__u.function(0);
00108 const ScalarFunctionBase& u1 = *__u.function(1);
00109 const ScalarFunctionBase& u2 = *__u.function(2);
00110
00111 const Connectivity<Structured3DMesh>& connectivity = __mesh.connectivity();
00112 if (not(connectivity.hasCellToCells())) {
00113 ConnectivityBuilder<Structured3DMesh> c(__mesh);
00114 c.generates(Connectivity<Structured3DMesh>::CellToCells);
00115 }
00116
00117 TinyVector<3, real_t> X0 = X;
00118
00119 TinyVector<3, real_t> Xhat0;
00120 {
00121 ConformTransformationQ1CartesianHexahedron T0(*h);
00122 T0.invertT(X0, Xhat0);
00123 }
00124
00125 real_t dt0 = __deltaT;
00126
00127 const size_t faceNumberConverter[6] = {4,2,1,3,0,5};
00128
00129 do {
00130 const CartesianHexahedron& H = (*h);
00131 ConformTransformationQ1CartesianHexahedron T(H);
00132
00133 T.value(Xhat0,X0);
00134
00135 TinyVector<3, real_t> X1;
00136 X1[0] = X0[0]-u0(X0)*dt0;
00137 X1[1] = X0[1]-u1(X0)*dt0;
00138 X1[2] = X0[2]-u2(X0)*dt0;
00139
00140 TinyVector<3, real_t> Xhat1;
00141 T.invertT(X1, Xhat1);
00142
00143 if(( Xhat1[0] >= 0)
00144 and(Xhat1[1] >= 0)
00145 and(Xhat1[2] >= 0)
00146 and(Xhat1[0] <= 1)
00147 and(Xhat1[1] <= 1)
00148 and(Xhat1[2] <= 1)) {
00149 dt0 = 0;
00150 X0 = X1;
00151 } else {
00152
00153 const TinyVector<3, real_t> deltaX = Xhat1-Xhat0;
00154
00155
00156 TinyVector<3, real_t> x0 = 0;
00157 for (size_t i=0; i<3; ++i) {
00158 if (deltaX[i]>0) x0[i] = 1;
00159 }
00160
00161
00162 TinyVector<3, real_t> coef = std::numeric_limits<real_t>::max();
00163 for (size_t i=0; i<3; ++i) {
00164 if (std::abs(deltaX[i])>0) {
00165 coef[i] = std::abs((x0[i]-Xhat0[i])/deltaX[i]);
00166 }
00167 }
00168
00169 size_t minimumCoefficentNumber = 0;
00170 for (size_t i=1; i<3; ++i) {
00171 minimumCoefficentNumber
00172 = (coef[minimumCoefficentNumber]<coef[i])?minimumCoefficentNumber:i;
00173 }
00174
00175 const size_t outGoingFace
00176 = faceNumberConverter[2*minimumCoefficentNumber + ((deltaX[minimumCoefficentNumber]>0)?1:0)];
00177
00178 const real_t dt = dt0*coef[minimumCoefficentNumber];
00179
00180 Xhat0 += coef[minimumCoefficentNumber] * deltaX;
00181 dt0-=dt;
00182
00183 h = connectivity.cells(*h)[outGoingFace];
00184 if (h.end()) {
00185 T.value(Xhat0,X0);
00186 dt0=0;
00187 }
00188
00189
00190
00191 Xhat0[minimumCoefficentNumber] = 1-x0[minimumCoefficentNumber];
00192 }
00193 } while (dt0>0);
00194 return __phi(X0);
00195 }
00196
00202 bool canBeSimplified() const
00203 {
00204 return false;
00205 }
00206
00215 Convection(const ScalarFunctionBase& phi,
00216 const FieldOfScalarFunction& u,
00217 const real_t& dt,
00218 const Structured3DMesh& M)
00219 : ScalarFunctionBase(ScalarFunctionBase::convection),
00220 __deltaT(dt),
00221 __mesh(M),
00222 __u(u),
00223 __phi(phi)
00224 {
00225 if (__u.numberOfComponents() != 3) {
00226 throw ErrorHandler(__FILE__,__LINE__,
00227 "Convection needs a 3 component field, you provided "+stringify(__u),
00228 ErrorHandler::normal);
00229 }
00230 }
00231
00236 ~Convection()
00237 {
00238 ;
00239 }
00240 };
00241
00250 template <>
00251 class Convection<MeshOfTetrahedra>
00252 : public ScalarFunctionBase
00253 {
00254 private:
00255 std::ostream& __put(std::ostream& os) const
00256 {
00257 os << "convect(" << __u << ","
00258 << __deltaT << ',' << __phi << ')';
00259 return os;
00260 }
00261
00263 const real_t __deltaT;
00264
00266 const MeshOfTetrahedra& __mesh;
00267
00269 const FieldOfScalarFunction& __u;
00270
00272 const ScalarFunctionBase& __phi;
00273 public:
00275 real_t operator()(const TinyVector<3>& X) const
00276 {
00277 const real_t epsilon = 1E-6;
00278 MeshOfTetrahedra::const_iterator t = __mesh.find(X[0], X[1], X[2]);
00279 if (t.end()) return 0;
00280
00281 const ScalarFunctionBase& u0 = *__u.function(0);
00282 const ScalarFunctionBase& u1 = *__u.function(1);
00283 const ScalarFunctionBase& u2 = *__u.function(2);
00284
00285 const Connectivity<MeshOfTetrahedra>& connectivity = __mesh.connectivity();
00286 if (not(connectivity.hasCellToCells())) {
00287 ConnectivityBuilder<MeshOfTetrahedra> c(__mesh);
00288 c.generates(Connectivity<MeshOfTetrahedra>::CellToCells);
00289 }
00290
00291 TinyVector<3, real_t> X0 = X;
00292
00293 real_t dt0 = __deltaT;
00294 do {
00295 TinyVector<3, real_t> X1;
00296 X1[0] = X0[0]-u0(X0)*dt0;
00297 X1[1] = X0[1]-u1(X0)*dt0;
00298 X1[2] = X0[2]-u2(X0)*dt0;
00299
00300 TinyVector<4, real_t> lambda1;
00301 const Tetrahedron& T = (*t);
00302 T.getBarycentricCoordinates(X1, lambda1);
00303 if((lambda1[0]>-epsilon)
00304 and(lambda1[1]>-epsilon)
00305 and(lambda1[2]>-epsilon)
00306 and(lambda1[3]>-epsilon)) {
00307 dt0 = 0;
00308 X0 = X1;
00309 } else {
00310 TinyVector<4, real_t> lambda0;
00311 T.getBarycentricCoordinates(X0, lambda0);
00312
00313 TinyVector<4, real_t> deltaLambda = lambda1-lambda0;
00314 real_t coeff = std::numeric_limits<real_t>::max();
00315 size_t outGoingFace=std::numeric_limits<size_t>::max();
00316 for (size_t i=0; i<4; ++i) {
00317 if (lambda1[i] <= -epsilon) {
00318 real_t tmp = -lambda0[i]/deltaLambda[i];
00319 if ((std::abs(tmp) < std::abs(coeff))) {
00320 coeff = tmp;
00321 outGoingFace = i;
00322 }
00323 }
00324 }
00325 if (not(std::abs(lambda0[outGoingFace]) < epsilon)) {
00326 const real_t dt = dt0*coeff;
00327 dt0-=dt;
00328 X0 += coeff * (X1-X0);
00329 T.getBarycentricCoordinates(X0, lambda0);
00330 }
00331
00332 t = connectivity.cells(*t)[outGoingFace];
00333 if (t.end()) { dt0=0; }
00334 }
00335 } while (dt0>0);
00336 return __phi(X0);
00337 }
00338
00344 bool canBeSimplified() const
00345 {
00346 return false;
00347 }
00348
00354 Convection(const Convection<MeshOfTetrahedra>& C)
00355 : ScalarFunctionBase(ScalarFunctionBase::convection),
00356 __deltaT(C.__deltaT),
00357 __mesh(C.__mesh),
00358 __u(C.__u),
00359 __phi(C.__phi)
00360 {
00361 ;
00362 }
00363
00372 Convection(const ScalarFunctionBase& phi,
00373 const FieldOfScalarFunction& u,
00374 const real_t& dt,
00375 const MeshOfTetrahedra& M)
00376 : ScalarFunctionBase(ScalarFunctionBase::convection),
00377 __deltaT(dt),
00378 __mesh(M),
00379 __u(u),
00380 __phi(phi)
00381 {
00382 ;
00383 }
00384
00389 ~Convection()
00390 {
00391 ;
00392 }
00393 };
00402 template <>
00403 class Convection<MeshOfHexahedra>
00404 : public ScalarFunctionBase
00405 {
00406 private:
00407 std::ostream& __put(std::ostream& os) const
00408 {
00409 os << "convect(" << __u << ","
00410 << __deltaT << ',' << __phi << ')';
00411 return os;
00412 }
00413
00415 const real_t __deltaT;
00416
00418 const MeshOfHexahedra& __mesh;
00419
00421 const FieldOfScalarFunction& __u;
00422
00424 const ScalarFunctionBase& __phi;
00425
00426 public:
00428 real_t operator()(const TinyVector<3>& X) const
00429 {
00430 MeshOfHexahedra::const_iterator h = __mesh.find(X[0], X[1], X[2]);
00431 if (h.end()) return 0;
00432
00433 const ScalarFunctionBase& u0 = *__u.function(0);
00434 const ScalarFunctionBase& u1 = *__u.function(1);
00435 const ScalarFunctionBase& u2 = *__u.function(2);
00436
00437 const Connectivity<MeshOfHexahedra>& connectivity = __mesh.connectivity();
00438 if (not(connectivity.hasCellToCells())) {
00439 ConnectivityBuilder<MeshOfHexahedra> c(__mesh);
00440 c.generates(Connectivity<MeshOfHexahedra>::CellToCells);
00441 }
00442
00443 TinyVector<3, real_t> X0 = X;
00444
00445 TinyVector<3, real_t> Xhat0;
00446 {
00447 ConformTransformationQ1Hexahedron T0(*h);
00448 T0.invertT(X0, Xhat0);
00449 }
00450
00451 real_t dt0 = __deltaT;
00452
00453 const size_t faceNumberConverter[6] = {4,2,1,3,0,5};
00454
00455 do {
00456 const Hexahedron& H = (*h);
00457 ConformTransformationQ1Hexahedron T(H);
00458
00459 T.value(Xhat0,X0);
00460
00461 TinyVector<3, real_t> X1;
00462 X1[0] = X0[0]-u0(X0)*dt0;
00463 X1[1] = X0[1]-u1(X0)*dt0;
00464 X1[2] = X0[2]-u2(X0)*dt0;
00465
00466 TinyVector<3, real_t> Xhat1;
00467 T.invertT(X1, Xhat1);
00468
00469 if(( Xhat1[0] >= 0)
00470 and(Xhat1[1] >= 0)
00471 and(Xhat1[2] >= 0)
00472 and(Xhat1[0] <= 1)
00473 and(Xhat1[1] <= 1)
00474 and(Xhat1[2] <= 1)) {
00475 dt0 = 0;
00476 X0 = X1;
00477 } else {
00478
00479 const TinyVector<3, real_t> deltaX = Xhat1-Xhat0;
00480
00481
00482 TinyVector<3, real_t> x0 = 0;
00483 for (size_t i=0; i<3; ++i) {
00484 if (deltaX[i]>0) x0[i] = 1;
00485 }
00486
00487
00488 TinyVector<3, real_t> coef = std::numeric_limits<real_t>::max();
00489 for (size_t i=0; i<3; ++i) {
00490 if (std::abs(deltaX[i])>0) {
00491 coef[i] = std::abs((x0[i]-Xhat0[i])/deltaX[i]);
00492 }
00493 }
00494
00495 size_t minimumCoefficentNumber = 0;
00496 for (size_t i=1; i<3; ++i) {
00497 minimumCoefficentNumber
00498 = (coef[minimumCoefficentNumber]<coef[i])?minimumCoefficentNumber:i;
00499 }
00500
00501 const size_t outGoingFace
00502 = faceNumberConverter[2*minimumCoefficentNumber + ((deltaX[minimumCoefficentNumber]>0)?1:0)];
00503
00504 const real_t dt = dt0*coef[minimumCoefficentNumber];
00505
00506 Xhat0 += coef[minimumCoefficentNumber] * deltaX;
00507 dt0-=dt;
00508
00509 h = connectivity.cells(*h)[outGoingFace];
00510 if (h.end()) {
00511 T.value(Xhat0,X0);
00512 dt0=0;
00513 }
00514
00515
00516
00517 Xhat0[minimumCoefficentNumber] = 1-x0[minimumCoefficentNumber];
00518 }
00519 } while (dt0>0);
00520
00521 return __phi(X0);
00522 }
00523
00529 bool canBeSimplified() const
00530 {
00531 return false;
00532 }
00533
00539 Convection(const Convection<MeshOfHexahedra>& C)
00540 : ScalarFunctionBase(ScalarFunctionBase::convection),
00541 __deltaT(C.__deltaT),
00542 __mesh(C.__mesh),
00543 __u(C.__u),
00544 __phi(C.__phi)
00545 {
00546 ;
00547 }
00548
00557 Convection(const ScalarFunctionBase& phi,
00558 const FieldOfScalarFunction& u,
00559 const real_t& dt,
00560 const MeshOfHexahedra& M)
00561 : ScalarFunctionBase(ScalarFunctionBase::convection),
00562 __deltaT(dt),
00563 __mesh(M),
00564 __u(u),
00565 __phi(phi)
00566 {
00567 ;
00568 }
00569
00574 ~Convection()
00575 {
00576 ;
00577 }
00578 };
00579
00580 #endif // CONVECTION_HPP