00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ScalarFunctionBuilder.hpp>
00021
00022 #include <ScalarFunctionConstant.hpp>
00023
00024 #include <ScalarFunctionCFunction.hpp>
00025
00026 #include <ScalarFunctionUnaryMinus.hpp>
00027 #include <ScalarFunctionNot.hpp>
00028
00029 #include <ScalarFunctionModulo.hpp>
00030
00031 #include <ScalarFunctionSum.hpp>
00032 #include <ScalarFunctionDifference.hpp>
00033 #include <ScalarFunctionProduct.hpp>
00034 #include <ScalarFunctionDivision.hpp>
00035 #include <ScalarFunctionPower.hpp>
00036
00037 #include <ScalarFunctionMin.hpp>
00038 #include <ScalarFunctionMax.hpp>
00039
00040 #include <ScalarFunctionGreaterThan.hpp>
00041 #include <ScalarFunctionGreaterEqual.hpp>
00042 #include <ScalarFunctionLowerThan.hpp>
00043 #include <ScalarFunctionLowerEqual.hpp>
00044
00045 #include <ScalarFunctionNotEqual.hpp>
00046 #include <ScalarFunctionEqual.hpp>
00047
00048 #include <ScalarFunctionAnd.hpp>
00049 #include <ScalarFunctionOr.hpp>
00050 #include <ScalarFunctionXor.hpp>
00051
00052 #include <FEMFunctionBase.hpp>
00053
00054 #include <FEMFunctionBuilder.hpp>
00055
00056 class ScalarFunctionBuilder::Simplifier
00057 {
00058 struct BinaryOperatorModulo
00059 {
00068 static real_t eval(const real_t& x,const real_t& y) { return static_cast<int>(x)%static_cast<int>(y); }
00069 };
00070
00071 struct BinaryOperatorSum
00072 {
00081 static real_t eval(const real_t& x,const real_t& y) { return x+y; }
00082 };
00083
00084 struct BinaryOperatorDifference
00085 {
00094 static real_t eval(const real_t& x,const real_t& y) { return x-y; }
00095 };
00096
00097 struct BinaryOperatorProduct
00098 {
00107 static real_t eval(const real_t& x,const real_t& y) { return x*y; }
00108 };
00109
00110 struct BinaryOperatorDivision
00111 {
00120 static real_t eval(const real_t& x,const real_t& y) { return x/y; }
00121 };
00122
00123 struct BinaryOperatorPower
00124 {
00133 static real_t eval(const real_t& x,const real_t& y) { return std::pow(x,y); }
00134 };
00135
00136 struct BinaryOperatorMin
00137 {
00146 static real_t eval(const real_t& x,const real_t& y) { return std::min(x,y); }
00147 };
00148
00149 struct BinaryOperatorMax
00150 {
00159 static real_t eval(const real_t& x,const real_t& y) { return std::max(x,y); }
00160 };
00161
00170 template <typename BinaryOperatorType>
00171 ConstReferenceCounting<ScalarFunctionBase>
00172 __getOperatorF1F2SimplifiedFunction(const ScalarFunctionConstant& f1,
00173 const ScalarFunctionConstant& f2) const
00174 {
00175 return new ScalarFunctionConstant(BinaryOperatorType::eval(f1(0),
00176 f2(0)));
00177 }
00178
00188 template <typename BinaryOperatorType>
00189 ConstReferenceCounting<ScalarFunctionBase>
00190 __getOperatorF1F2SimplifiedFunction(const ScalarFunctionConstant& f1,
00191 const FEMFunctionBase& f2) const
00192 {
00193 Vector<real_t> femValues(f2.values().size());
00194
00195 const real_t constantValue = f1(0);
00196
00197 const real_t outsideValue = BinaryOperatorType::eval(constantValue,
00198 f2.outsideValue());
00199
00200 for (size_t i=0; i<femValues.size(); ++i) {
00201 femValues[i] = BinaryOperatorType::eval(constantValue,f2[i]);
00202 }
00203
00204 FEMFunctionBuilder builder;
00205 builder.build(f2.discretizationType(),
00206 f2.baseMesh(),
00207 femValues,
00208 outsideValue);
00209 return builder.getBuiltScalarFunction();
00210 }
00211
00221 template <typename BinaryOperatorType>
00222 ConstReferenceCounting<ScalarFunctionBase>
00223 __getOperatorF1F2SimplifiedFunction(const FEMFunctionBase& f1,
00224 const ScalarFunctionConstant& f2) const
00225 {
00226 Vector<real_t> femValues(f1.values().size());
00227
00228 const real_t constantValue = f2(0);
00229
00230 for (size_t i=0; i<femValues.size(); ++i) {
00231 femValues[i] = BinaryOperatorType::eval(f1[i],constantValue);
00232 }
00233
00234 const real_t outsideValue = BinaryOperatorType::eval(f1.outsideValue(),
00235 constantValue);
00236
00237 FEMFunctionBuilder builder;
00238 builder.build(f1.discretizationType(),
00239 f1.baseMesh(),
00240 femValues,
00241 outsideValue);
00242 return builder.getBuiltScalarFunction();
00243 }
00244
00254 template <typename BinaryOperatorType>
00255 ConstReferenceCounting<ScalarFunctionBase>
00256 __getOperatorF1F2SimplifiedFunction(const FEMFunctionBase& f1,
00257 const FEMFunctionBase& f2) const
00258 {
00259 Vector<real_t> femValues(f1.values().size());
00260
00261 ASSERT(f1.discretizationType() == f2.discretizationType());
00262 ASSERT(f1.baseMesh() == f2.baseMesh());
00263
00264 for (size_t i=0; i<femValues.size(); ++i) {
00265 femValues[i] = BinaryOperatorType::eval(f1[i],f2[i]);
00266 }
00267
00268 const real_t outsideValue = BinaryOperatorType::eval(f1.outsideValue(),
00269 f2.outsideValue());
00270
00271 FEMFunctionBuilder builder;
00272 builder.build(f1.discretizationType(),
00273 f1.baseMesh(),
00274 femValues,
00275 outsideValue);
00276 return builder.getBuiltScalarFunction();
00277 }
00278
00279
00288 template <typename BinaryOperatorType,
00289 typename FunctionType1>
00290 ConstReferenceCounting<ScalarFunctionBase>
00291 __getOperatorF1SimplifiedFunction(const FunctionType1& f,
00292 const ScalarFunctionBase& f2) const
00293 {
00294 switch (f2.type()) {
00295 case ScalarFunctionBase::constant: {
00296 const ScalarFunctionConstant& g = static_cast<const ScalarFunctionConstant&>(f2);
00297 return this->__getOperatorF1F2SimplifiedFunction<BinaryOperatorType>(f,g);
00298 }
00299 case ScalarFunctionBase::femfunction: {
00300 const FEMFunctionBase& g = static_cast<const FEMFunctionBase&>(f2);
00301 return this->__getOperatorF1F2SimplifiedFunction<BinaryOperatorType>(f,g);
00302 }
00303 default: {
00304 throw ErrorHandler(__FILE__,__LINE__,
00305 "unexpected function type",
00306 ErrorHandler::unexpected);
00307 }
00308 }
00309 return 0;
00310 }
00311
00320 template <typename BinaryOperatorType>
00321 ConstReferenceCounting<ScalarFunctionBase>
00322 __getOperatorSimplifiedFunction(const ScalarFunctionBase& f1,
00323 const ScalarFunctionBase& f2) const
00324 {
00325 switch (f1.type()) {
00326 case ScalarFunctionBase::constant: {
00327 const ScalarFunctionConstant& f = static_cast<const ScalarFunctionConstant&>(f1);
00328 return this->__getOperatorF1SimplifiedFunction<BinaryOperatorType>(f,f2);
00329 }
00330 case ScalarFunctionBase::femfunction: {
00331 const FEMFunctionBase& f = static_cast<const FEMFunctionBase&>(f1);
00332 if (f2.type() == ScalarFunctionBase::femfunction) {
00333 const FEMFunctionBase& g = static_cast<const FEMFunctionBase&>(f2);
00334 if (not(f.hasSameType(g))) {
00335 return 0;
00336 }
00337 }
00338 return this->__getOperatorF1SimplifiedFunction<BinaryOperatorType>(f,f2);
00339 }
00340 default: {
00341 throw ErrorHandler(__FILE__,__LINE__,
00342 "unexpected function type",
00343 ErrorHandler::unexpected);
00344 }
00345 }
00346 return 0;
00347 }
00348
00349 public:
00359 ConstReferenceCounting<ScalarFunctionBase>
00360 simplify(const BinaryOperation& binaryOperation,
00361 const ScalarFunctionBase& f,
00362 const ScalarFunctionBase& g) const
00363 {
00364 if (not(f.canBeSimplified() and g.canBeSimplified())) {
00365 return 0;
00366 }
00367
00368 switch (binaryOperation.type()) {
00369 case BinaryOperation::modulo: {
00370 return __getOperatorSimplifiedFunction<BinaryOperatorModulo>(f,g);
00371 }
00372 case BinaryOperation::sum: {
00373 return __getOperatorSimplifiedFunction<BinaryOperatorSum>(f,g);
00374 }
00375 case BinaryOperation::difference: {
00376 return __getOperatorSimplifiedFunction<BinaryOperatorDifference>(f,g);
00377 }
00378 case BinaryOperation::product: {
00379 return __getOperatorSimplifiedFunction<BinaryOperatorProduct>(f,g);
00380 }
00381 case BinaryOperation::division: {
00382 return __getOperatorSimplifiedFunction<BinaryOperatorDivision>(f,g);
00383 }
00384 case BinaryOperation::power: {
00385 return __getOperatorSimplifiedFunction<BinaryOperatorPower>(f,g);
00386 }
00387 case BinaryOperation::min: {
00388 return __getOperatorSimplifiedFunction<BinaryOperatorMin>(f,g);
00389 }
00390 case BinaryOperation::max: {
00391 return __getOperatorSimplifiedFunction<BinaryOperatorMax>(f,g);
00392 }
00393
00394 case BinaryOperation::gt:
00395 case BinaryOperation::lt:
00396 case BinaryOperation::ge:
00397 case BinaryOperation::le:
00398 case BinaryOperation::eq:
00399 case BinaryOperation::ne:
00400 case BinaryOperation::or_:
00401 case BinaryOperation::xor_:
00402 case BinaryOperation::and_: {
00403 return 0;
00404 }
00405 case BinaryOperation::undefined:
00406 default: {
00407 throw ErrorHandler(__FILE__,__LINE__,
00408 "not implemented",
00409 ErrorHandler::unexpected);
00410 return 0;
00411 }
00412 }
00413 return 0;
00414 }
00415
00416
00421 Simplifier()
00422 {
00423 ;
00424 }
00425
00430 ~Simplifier()
00431 {
00432 ;
00433 }
00434 };
00435
00436 void ScalarFunctionBuilder::
00437 setFunction(ConstReferenceCounting<ScalarFunctionBase> f)
00438 {
00439 ASSERT(__builtFunction == 0);
00440 __builtFunction = f;
00441 }
00442
00443 void ScalarFunctionBuilder::
00444 setBinaryOperation(const BinaryOperation binaryOperation,
00445 ConstReferenceCounting<ScalarFunctionBase> f)
00446 {
00447 ASSERT(__builtFunction != 0);
00448
00449 Simplifier simplifier;
00450
00451 ConstReferenceCounting<ScalarFunctionBase>
00452 simplifiedFunction = simplifier.simplify(binaryOperation,
00453 *__builtFunction,
00454 *f);
00455 if (simplifiedFunction) {
00456 ffout(4) << " * algebraic simplification of "
00457 << *__builtFunction << ' ' << binaryOperation << ' ' << *f << '\n';
00458 __builtFunction = simplifiedFunction;
00459 } else {
00460 switch (binaryOperation.type()) {
00461 case BinaryOperation::modulo: {
00462 __builtFunction = new ScalarFunctionModulo(__builtFunction, f);
00463 break;
00464 }
00465 case BinaryOperation::sum: {
00466 __builtFunction = new ScalarFunctionSum(__builtFunction, f);
00467 break;
00468 }
00469 case BinaryOperation::difference: {
00470 __builtFunction = new ScalarFunctionDifference(__builtFunction, f);
00471 break;
00472 }
00473 case BinaryOperation::product: {
00474 __builtFunction = new ScalarFunctionProduct(__builtFunction, f);
00475 break;
00476 }
00477 case BinaryOperation::division: {
00478 __builtFunction = new ScalarFunctionDivision(__builtFunction, f);
00479 break;
00480 }
00481 case BinaryOperation::power: {
00482 __builtFunction = new ScalarFunctionPower(__builtFunction, f);
00483 break;
00484 }
00485
00486 case BinaryOperation::min: {
00487 __builtFunction = new ScalarFunctionMin(__builtFunction, f);
00488 break;
00489 }
00490 case BinaryOperation::max: {
00491 __builtFunction = new ScalarFunctionMax(__builtFunction, f);
00492 break;
00493 }
00494
00495
00496 case BinaryOperation::gt: {
00497 __builtFunction = new ScalarFunctionGreaterThan(__builtFunction, f);
00498 break;
00499 }
00500 case BinaryOperation::ge: {
00501 __builtFunction = new ScalarFunctionGreaterEqual(__builtFunction, f);
00502 break;
00503 }
00504 case BinaryOperation::lt: {
00505 __builtFunction = new ScalarFunctionLowerThan(__builtFunction, f);
00506 break;
00507 }
00508 case BinaryOperation::le: {
00509 __builtFunction = new ScalarFunctionLowerEqual(__builtFunction, f);
00510 break;
00511 }
00512 case BinaryOperation::eq: {
00513 __builtFunction = new ScalarFunctionEqual(__builtFunction, f);
00514 break;
00515 }
00516 case BinaryOperation::ne: {
00517 __builtFunction = new ScalarFunctionNotEqual(__builtFunction, f);
00518 break;
00519 }
00520
00521 case BinaryOperation::and_: {
00522 __builtFunction = new ScalarFunctionAnd(__builtFunction, f);
00523 break;
00524 }
00525 case BinaryOperation::or_: {
00526 __builtFunction = new ScalarFunctionOr(__builtFunction, f);
00527 break;
00528 }
00529 case BinaryOperation::xor_: {
00530 __builtFunction = new ScalarFunctionXor(__builtFunction, f);
00531 break;
00532 }
00533
00534 default: {
00535 throw ErrorHandler(__FILE__,__LINE__,
00536 "Not implemented binary operation",
00537 ErrorHandler::unexpected);
00538 }
00539 }
00540 }
00541 }
00542
00543 void ScalarFunctionBuilder::
00544 setUnaryMinus()
00545 {
00546 ASSERT(__builtFunction != 0);
00547 switch (__builtFunction->type()) {
00548 case ScalarFunctionBase::constant: {
00549 const ScalarFunctionConstant& f
00550 = static_cast<const ScalarFunctionConstant&>(*__builtFunction);
00551 const real_t value = -f(0);
00552
00553 ffout(4) << " * algebraic simplification of -" << f << '\n';
00554
00555 __builtFunction = new ScalarFunctionConstant(value);
00556 break;
00557 }
00558 case ScalarFunctionBase::femfunction: {
00559 const FEMFunctionBase& f
00560 = static_cast<const FEMFunctionBase&>(*__builtFunction);
00561 Vector<real_t> femValues(f.values().size());
00562
00563 for (size_t i=0; i<femValues.size(); ++i) {
00564 femValues[i] = -f[i];
00565 }
00566
00567 const real_t outsideValue = -f.outsideValue();
00568
00569 ffout(4) << " * algebraic simplification of -" << f << '\n';
00570
00571 FEMFunctionBuilder builder;
00572 builder.build(f.discretizationType(),
00573 f.baseMesh(),
00574 femValues,
00575 outsideValue);
00576 __builtFunction = builder.getBuiltScalarFunction();
00577 break;
00578 }
00579 default: {
00580 __builtFunction = new ScalarFunctionUnaryMinus(__builtFunction);
00581 }
00582 }
00583 }
00584
00585 void ScalarFunctionBuilder::
00586 setNot()
00587 {
00588 ASSERT(__builtFunction != 0);
00589 __builtFunction = new ScalarFunctionNot(__builtFunction);
00590 }
00591
00592
00593 void ScalarFunctionBuilder::
00594 setCFunction(const std::string& cfunction)
00595 {
00596 ASSERT(__builtFunction != 0);
00597 __builtFunction = new ScalarFunctionCFunction(cfunction, __builtFunction);
00598 }