00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ScalarFunctionIntegrate.hpp>
00021 #include <ErrorHandler.hpp>
00022
00023 #include <Structured3DMesh.hpp>
00024 #include <ConnectivityBuilder.hpp>
00025 #include <ConformTransformation.hpp>
00026
00027 std::ostream&
00028 ScalarFunctionIntegrate::
00029 __put(std::ostream& os) const
00030 {
00031 switch(__direction) {
00032 case ScalarFunctionIntegrate::x: {
00033 os << "int[x](";
00034 break;
00035 }
00036 case ScalarFunctionIntegrate::y: {
00037 os << "int[y](";
00038 break;
00039 }
00040 case ScalarFunctionIntegrate::z: {
00041 os << "int[z](";
00042 break;
00043 }
00044 default: {
00045 throw ErrorHandler(__FILE__,__LINE__,
00046 "unknown integrate direction",
00047 ErrorHandler::unexpected);
00048 }
00049 }
00050 os << *__functionToIntegrate << ')';
00051 return os;
00052 }
00053
00054 template <typename MeshType>
00055 real_t
00056 ScalarFunctionIntegrate::
00057 __evaluate(const TinyVector<3,real_t>& X) const
00058 {
00059 throw ErrorHandler(__FILE__,__LINE__,
00060 "mesh type not supported",
00061 ErrorHandler::unexpected);
00062 return 0;
00063 }
00064
00065 template <>
00066 real_t
00067 ScalarFunctionIntegrate::
00068 __evaluate<Structured3DMesh>(const TinyVector<3,real_t>& X) const
00069 {
00070 const Mesh& baseMesh = *__functionToIntegrate->baseMesh();
00071 const Structured3DMesh& mesh = static_cast<const Structured3DMesh&>(baseMesh);
00072
00073 const real_t lowerBound = (*__lowerBound)(X);
00074 const real_t upperBound = (*__upperBound)(X);
00075
00076 const real_t minBound = std::min(lowerBound,upperBound);
00077 const real_t maxBound = std::max(lowerBound,upperBound);
00078
00079 TinyVector<3, real_t> a = X;
00080 TinyVector<3, real_t> b = X;
00081
00082 a[__direction] = std::max(mesh.shape().a()[__direction], minBound);
00083 b[__direction] = std::min(mesh.shape().b()[__direction], maxBound);
00084
00085 Structured3DMesh::const_iterator h = mesh.find(a);
00086
00087 if (h.end()) {
00088 return 0;
00089 }
00090
00091 const Connectivity<Structured3DMesh>& connectivity = mesh.connectivity();
00092 if (not(connectivity.hasCellToCells())) {
00093 ConnectivityBuilder<Structured3DMesh> c(mesh);
00094 c.generates(Connectivity<Structured3DMesh>::CellToCells);
00095 }
00096
00097 TinyVector<3, real_t> X0 = a;
00098
00099 TinyVector<3, real_t> Xhat0;
00100 {
00101 ConformTransformationQ1CartesianHexahedron T0(*h);
00102 T0.invertT(X0, Xhat0);
00103 }
00104
00105 const TinyVector<3,real_t> u = b-a;
00106 real_t dt0 = 1;
00107
00108 const size_t faceNumberConverter[6] = {4,2,1,3,0,5};
00109
00110 real_t integrale = 0;
00111
00112 do {
00113 const CartesianHexahedron& H = (*h);
00114 ConformTransformationQ1CartesianHexahedron T(H);
00115
00116 a=X0;
00117
00118 T.value(Xhat0,X0);
00119
00120 integrale += (*__functionToIntegrate)(0.5*(X0+a))*(X0[__direction]-a[__direction]);
00121
00122 TinyVector<3, real_t> X1 = X0+dt0*u;
00123
00124 TinyVector<3, real_t> Xhat1;
00125 T.invertT(b, Xhat1);
00126
00127 if(( Xhat1[0] >= 0)
00128 and(Xhat1[1] >= 0)
00129 and(Xhat1[2] >= 0)
00130 and(Xhat1[0] <= 1)
00131 and(Xhat1[1] <= 1)
00132 and(Xhat1[2] <= 1)) {
00133
00134 dt0 = 0;
00135 integrale += (*__functionToIntegrate)(0.5*(X0+X1))*Norm(X1-X0);
00136 } else {
00137
00138 const TinyVector<3, real_t> deltaX = Xhat1-Xhat0;
00139
00140
00141 TinyVector<3, real_t> x0 = 0;
00142 for (size_t i=0; i<3; ++i) {
00143 if (deltaX[i]>0) x0[i] = 1;
00144 }
00145
00146
00147 TinyVector<3, real_t> coef = std::numeric_limits<real_t>::max();
00148 for (size_t i=0; i<3; ++i) {
00149 if (std::abs(deltaX[i])>0) {
00150 coef[i] = std::abs((x0[i]-Xhat0[i])/deltaX[i]);
00151 }
00152 }
00153
00154 size_t minimumCoefficentNumber = 0;
00155 for (size_t i=1; i<3; ++i) {
00156 minimumCoefficentNumber
00157 = (coef[minimumCoefficentNumber]<coef[i])?minimumCoefficentNumber:i;
00158 }
00159
00160 const size_t outGoingFace
00161 = faceNumberConverter[2*minimumCoefficentNumber + ((deltaX[minimumCoefficentNumber]>0)?1:0)];
00162
00163 const real_t dt = dt0*coef[minimumCoefficentNumber];
00164
00165 Xhat0 += coef[minimumCoefficentNumber] * deltaX;
00166 dt0-=dt;
00167
00168 h = connectivity.cells(*h)[outGoingFace];
00169 if (h.end()) {
00170 throw ErrorHandler(__FILE__,__LINE__,
00171 "cannot find next cell",
00172 ErrorHandler::unexpected);
00173 }
00174
00175
00176 Xhat0[minimumCoefficentNumber] = 1-x0[minimumCoefficentNumber];
00177 }
00178 } while (dt0>0);
00179
00180 if (lowerBound == minBound) {
00181 return integrale;
00182 } else {
00183 return -integrale;
00184 }
00185 }
00186
00187 real_t
00188 ScalarFunctionIntegrate::
00189 operator()(const TinyVector<3, real_t>& X) const
00190 {
00191 const Mesh& baseMesh = *__functionToIntegrate->baseMesh();
00192 if (baseMesh.type() != Mesh::cartesianHexahedraMesh) {
00193 throw ErrorHandler(__FILE__,__LINE__,
00194 "Can only evaluate integrate functions on cartesian structured meshes",
00195 ErrorHandler::normal);
00196 }
00197
00198 return this->__evaluate<Structured3DMesh>(X);
00199 }
00200
00201 ScalarFunctionIntegrate::
00202 ScalarFunctionIntegrate(ConstReferenceCounting<ScalarFunctionBase> lowerBound,
00203 ConstReferenceCounting<ScalarFunctionBase> upperBound,
00204 ConstReferenceCounting<ScalarFunctionBase> functionToIntegrate,
00205 const ScalarFunctionIntegrate::Direction& direction)
00206 : ScalarFunctionBase(ScalarFunctionBase::integrate),
00207 __lowerBound(lowerBound),
00208 __upperBound(upperBound),
00209 __direction(direction)
00210 {
00211 if (functionToIntegrate->type() != ScalarFunctionBase::femfunction) {
00212 std::stringstream errorMsg;
00213
00214 errorMsg << "cannot compute 1D integrale of non FEM functions :-(\n";
00215 errorMsg << "the function " << (*functionToIntegrate) << " is not of that kind"
00216 << std::ends;
00217
00218 throw ErrorHandler(__FILE__,__LINE__,
00219 errorMsg.str(),
00220 ErrorHandler::normal);
00221
00222 }
00223 const ScalarFunctionBase* f = functionToIntegrate;
00224 __functionToIntegrate = dynamic_cast<const FEMFunctionBase*>(f);
00225 }
00226
00227 ScalarFunctionIntegrate::
00228 ScalarFunctionIntegrate(const ScalarFunctionIntegrate& f)
00229 : ScalarFunctionBase(f),
00230 __lowerBound(f.__lowerBound),
00231 __upperBound(f.__upperBound),
00232 __functionToIntegrate(f.__functionToIntegrate),
00233 __direction(f.__direction)
00234 {
00235 ;
00236 }
00237
00238 ScalarFunctionIntegrate::
00239 ~ScalarFunctionIntegrate()
00240 {
00241 ;
00242 }