00001 /* @HEADER@ */ 00002 // ************************************************************************ 00003 // 00004 // Playa: Programmable Linear Algebra 00005 // Copyright 2012 Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 00009 // 00010 // Redistribution and use in source and binary forms, with or without 00011 // modification, are permitted provided that the following conditions are 00012 // met: 00013 // 00014 // 1. Redistributions of source code must retain the above copyright 00015 // notice, this list of conditions and the following disclaimer. 00016 // 00017 // 2. Redistributions in binary form must reproduce the above copyright 00018 // notice, this list of conditions and the following disclaimer in the 00019 // documentation and/or other materials provided with the distribution. 00020 // 00021 // 3. Neither the name of the Corporation nor the names of the 00022 // contributors may be used to endorse or promote products derived from 00023 // this software without specific prior written permission. 00024 // 00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY 00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE 00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00036 // 00037 // Questions? Contact Kevin Long (kevin.long@ttu.edu) 00038 // 00039 00040 /* @HEADER@ */ 00041 00042 #ifndef PLAYA_SIMPLE_ADDED_OP_IMPL_HPP 00043 #define PLAYA_SIMPLE_ADDED_OP_IMPL_HPP 00044 00045 00046 00047 #include "PlayaSimpleAddedOpDecl.hpp" 00048 #include "PlayaSimpleZeroOpDecl.hpp" 00049 #include "PlayaLinearCombinationImpl.hpp" 00050 #include "PlayaOut.hpp" 00051 #include "PlayaTabs.hpp" 00052 #include "Teuchos_Array.hpp" 00053 00054 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION 00055 #include "PlayaSimpleZeroOpImpl.hpp" 00056 #include "PlayaLinearOperatorImpl.hpp" 00057 #include "PlayaSimpleTransposedOpImpl.hpp" 00058 #endif 00059 00060 00061 namespace Playa 00062 { 00063 using namespace Teuchos; 00064 00065 00066 00067 /* 00068 * Represent a sum of operators A_0 + A_1 + ... + A_n. 00069 */ 00070 template <class Scalar> inline 00071 SimpleAddedOp<Scalar>::SimpleAddedOp( 00072 const Array<LinearOperator<Scalar> >& ops) 00073 : LinearOpWithSpaces<Scalar>( 00074 ops[0].domain(), ops[0].range() 00075 ) 00076 , ops_(ops) 00077 { 00078 TEUCHOS_TEST_FOR_EXCEPT(ops_.size() <= 1); 00079 for (int i=1; i<ops_.size(); i++) 00080 { 00081 TEUCHOS_TEST_FOR_EXCEPT(!(ops[i].range() == ops[0].range())); 00082 TEUCHOS_TEST_FOR_EXCEPT(!(ops[i].domain() == ops[0].domain())); 00083 } 00084 } 00085 00086 /* */ 00087 template <class Scalar> inline 00088 void SimpleAddedOp<Scalar>::apply(Teuchos::ETransp transApplyType, 00089 const Vector<Scalar>& in, 00090 Vector<Scalar> out) const 00091 { 00092 Tabs tab(0); 00093 PLAYA_MSG2(this->verb(), tab << "SimpleAddedOp::apply()"); 00094 00095 Vector<Scalar> tmp=out.copy(); 00096 tmp.zero(); 00097 for (int i=0; i<ops_.size(); i++) 00098 { 00099 Tabs tab1; 00100 PLAYA_MSG3(this->verb(), tab1 << "applying term i=" << i << " of " 00101 << ops_.size()); 00102 if (transApplyType == Teuchos::NO_TRANS) 00103 tmp += ops_[i] * in; 00104 else if (transApplyType == Teuchos::TRANS) 00105 tmp += ops_[i].transpose() * in; 00106 else 00107 TEUCHOS_TEST_FOR_EXCEPT(transApplyType != Teuchos::TRANS && transApplyType != Teuchos::NO_TRANS); 00108 } 00109 out.acceptCopyOf(tmp); 00110 00111 PLAYA_MSG2(this->verb(), tab << "done SimpleAddedOp::apply()"); 00112 } 00113 00114 /* */ 00115 template <class Scalar> inline 00116 std::string SimpleAddedOp<Scalar>::description() const 00117 { 00118 std::string rtn="("; 00119 for (int i=0; i<ops_.size(); i++) 00120 { 00121 if (i > 0) rtn += "+"; 00122 rtn += ops_[i].description(); 00123 } 00124 rtn += ")"; 00125 return rtn; 00126 } 00127 00128 00129 00130 template <class Scalar> inline 00131 LinearOperator<Scalar> addedOperator( 00132 const Array<LinearOperator<Scalar> >& ops) 00133 { 00134 /* We will strip out any zero operators */ 00135 Array<LinearOperator<Scalar> > strippedOps; 00136 00137 for (int i=0; i<ops.size(); i++) 00138 { 00139 LinearOperator<Scalar> op_i = ops[i]; 00140 00141 /* Ignore any zero operators */ 00142 const SimpleZeroOp<Scalar>* zPtr 00143 = dynamic_cast<const SimpleZeroOp<Scalar>*>(op_i.ptr().get()); 00144 00145 if (zPtr != 0) continue; 00146 00147 strippedOps.append(op_i); 00148 } 00149 00150 TEUCHOS_TEST_FOR_EXCEPT(strippedOps.size() < 1); 00151 if (strippedOps.size()==1) return strippedOps[0]; 00152 00153 RCP<LinearOperatorBase<Scalar> > op 00154 = rcp(new SimpleAddedOp<Scalar>(strippedOps)); 00155 00156 return op; 00157 } 00158 00159 template <class Scalar> inline 00160 LinearOperator<Scalar> operator+(const LinearOperator<Scalar>& A, 00161 const LinearOperator<Scalar>& B) 00162 { 00163 return addedOperator(Array<LinearOperator<Scalar> >(tuple(A, B))); 00164 } 00165 00166 } 00167 00168 #endif