00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "TSFSerialVector.hpp"
00028 #include "TSFSerialVectorSpace.hpp"
00029 #include "Teuchos_TestForException.hpp"
00030 #include "Teuchos_dyn_cast.hpp"
00031 #include "Teuchos_Workspace.hpp"
00032 #include "Thyra_DefaultSpmdVector.hpp"
00033
00034 #include "Thyra_apply_op_helper.hpp"
00035 #include "RTOpPack_SPMD_apply_op.hpp"
00036 #include "RTOp_parallel_helpers.h"
00037
00038
00039 #ifndef HAVE_TEUCHOS_EXPLICIT_INSTANTIATION
00040 #include "TSFVectorImpl.hpp"
00041 #include "TSFLinearOperatorImpl.hpp"
00042 #endif
00043
00044 using namespace Teuchos;
00045 using namespace TSFExtended;
00046 using namespace Thyra;
00047
00048 using Teuchos::Range1D;
00049
00050
00051 SerialVector::SerialVector(
00052 const RCP<const VectorSpaceBase<double> >& vs)
00053 : VectorDefaultBase<double>(),
00054 vecSpace_(vs),
00055 data_(vs->dim()),
00056 globalDim_(vs->dim()),
00057 in_applyOpImpl_(false)
00058 {
00059 const SerialVectorSpace* rvs
00060 = dynamic_cast<const SerialVectorSpace*>(vs.get());
00061 TEST_FOR_EXCEPTION(rvs==0, std::runtime_error,
00062 "could not cast vector space to SerialVectorSpace in "
00063 "SerialVector ctor");
00064 }
00065
00066
00067 void SerialVector::applyOpImpl(const RTOpPack::RTOpT< double >& op,
00068 const ArrayView< const Ptr< const VectorBase< double > > > & vecs,
00069 const ArrayView< const Ptr< VectorBase< double > > > & targ_vecs,
00070 const Ptr< RTOpPack::ReductTarget > & reduct_obj,
00071 const OrdType global_offset_in
00072 ) const
00073 {
00074
00075
00076 const OrdType first_ele_offset_in = 0;
00077 const OrdType sub_dim_in = -1;
00078
00079 using Teuchos::null;
00080 using Teuchos::dyn_cast;
00081 using Teuchos::Workspace;
00082
00083 const int num_vecs = vecs.size();
00084 const int num_targ_vecs = targ_vecs.size();
00085
00086 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00087 Teuchos::RCP<Teuchos::FancyOStream>
00088 out = Teuchos::VerboseObjectBase::getDefaultOStream();
00089 Teuchos::OSTab tab(out);
00090 if(show_dump) {
00091 *out << "\nEntering SpmdVectorBase<double>::applyOp(...) ...\n";
00092 *out
00093 << "\nop = " << typeName(op)
00094 << "\nnum_vecs = " << num_vecs
00095 << "\nnum_targ_vecs = " << num_targ_vecs
00096 << "\nreduct_obj = " << reduct_obj
00097 << "\nfirst_ele_offset_in = " << first_ele_offset_in
00098 << "\nsub_dim_in = " << sub_dim_in
00099 << "\nglobal_offset_in = " << global_offset_in
00100 << "\n"
00101 ;
00102 }
00103 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00104
00105 Ptr<Teuchos::WorkspaceStore> wss = Teuchos::get_default_workspace_store().ptr();
00106
00107 #ifdef TEUCHOS_DEBUG
00108
00109 TEST_FOR_EXCEPTION(
00110 in_applyOpImpl_, std::invalid_argument
00111 ,"SpmdVectorBase<>::applyOp(...): Error, this method is being entered recursively which is a "
00112 "clear sign that one of the methods acquireDetachedView(...), releaseDetachedView(...) or commitDetachedView(...) "
00113 "was not implemented properly!"
00114 );
00115 Thyra::apply_op_validate_input(
00116 "SpmdVectorBase<>::applyOp(...)",*space(),
00117 op, vecs, targ_vecs, reduct_obj,
00118 global_offset_in
00119 );
00120 #endif
00121
00122
00123
00124 in_applyOpImpl_ = true;
00125
00126 const bool locallySerial = true;
00127 int localOffset = 0;
00128 int localSubDim = globalDim_;
00129
00130
00131
00132 OrdType overlap_first_local_ele_off = 0;
00133 OrdType overlap_local_sub_dim = 0;
00134 OrdType overlap_global_off = 0;
00135 if(localSubDim) {
00136 RTOp_parallel_calc_overlap(
00137 globalDim_, localSubDim, localOffset,
00138 first_ele_offset_in, sub_dim_in, global_offset_in,
00139 &overlap_first_local_ele_off, &overlap_local_sub_dim, &overlap_global_off
00140 );
00141 }
00142 const Range1D local_rng = (
00143 overlap_first_local_ele_off>=0
00144 ? Range1D( localOffset + overlap_first_local_ele_off, localOffset
00145 + overlap_first_local_ele_off + overlap_local_sub_dim - 1 )
00146 : Range1D::Invalid
00147 );
00148
00149 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00150 if(show_dump) {
00151 *out
00152 << "\noverlap_first_local_ele_off = " << overlap_first_local_ele_off
00153 << "\noverlap_local_sub_dim = " << overlap_local_sub_dim
00154 << "\noverlap_global_off = " << overlap_global_off
00155 << "\nlocal_rng = ["<<local_rng.lbound()<<","<<local_rng.ubound()<<"]"
00156 << "\n"
00157 ;
00158 }
00159 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00160
00161
00162 Workspace<RTOpPack::ConstSubVectorView<double> > sub_vecs(wss.get(),num_vecs);
00163 Workspace<RTOpPack::SubVectorView<double> > sub_targ_vecs(wss.get(),num_targ_vecs);
00164 if( overlap_first_local_ele_off >= 0 ) {
00165 {for(int k = 0; k < num_vecs; ++k ) {
00166 vecs[k]->acquireDetachedView( local_rng, &sub_vecs[k] );
00167 sub_vecs[k].setGlobalOffset( overlap_global_off );
00168 }}
00169 {for(int k = 0; k < num_targ_vecs; ++k ) {
00170 targ_vecs[k]->acquireDetachedView( local_rng, &sub_targ_vecs[k] );
00171 sub_targ_vecs[k].setGlobalOffset( overlap_global_off );
00172 }}
00173 }
00174
00175
00176
00177
00178 RTOpPack::SPMD_apply_op(
00179 NULL ,
00180 op,
00181 num_vecs,
00182 sub_vecs.getRawPtr(),
00183 num_targ_vecs,
00184 sub_targ_vecs.getRawPtr(),
00185 reduct_obj.get()
00186 );
00187
00188
00189 if (overlap_first_local_ele_off >= 0) {
00190 for (int k = 0; k < num_vecs; ++k ) {
00191 sub_vecs[k].setGlobalOffset(local_rng.lbound());
00192 vecs[k]->releaseDetachedView( &sub_vecs[k] );
00193 }
00194 for (int k = 0; k < num_targ_vecs; ++k ) {
00195 sub_targ_vecs[k].setGlobalOffset(local_rng.lbound());
00196 targ_vecs[k]->commitDetachedView( &sub_targ_vecs[k] );
00197 }
00198 }
00199
00200
00201 in_applyOpImpl_ = false;
00202
00203 #ifdef THYRA_SPMD_VECTOR_BASE_DUMP
00204 if(show_dump) {
00205 *out << "\nLeaving SpmdVectorBase<double>::applyOp(...) ...\n";
00206 }
00207 #endif // THYRA_SPMD_VECTOR_BASE_DUMP
00208
00209 }
00210
00211
00212
00213
00214 void SerialVector::acquireDetachedVectorViewImpl(
00215 const Teuchos::Range1D& rng_in,
00216 RTOpPack::ConstSubVectorView<double>* sub_vec) const
00217 {
00218
00219 if (rng_in == Range1D::Invalid)
00220 {
00221 sub_vec->initialize(rng_in.lbound(), 0, Teuchos::ArrayRCP<double>(), 1);
00222 return ;
00223 }
00224
00225
00226 const Range1D rng = validateRange(rng_in);
00227 int localOffset = 0;
00228 int localSubDim = globalDim_;
00229
00230
00231
00232 if (
00233 rng.lbound() < localOffset
00234 || localOffset + localSubDim - 1 < rng.ubound())
00235 {
00236 VectorDefaultBase<double>::acquireDetachedVectorViewImpl(rng_in,sub_vec);
00237 return ;
00238 }
00239
00240
00241 const double* localValues = &(data_[0]);
00242 Teuchos::ArrayRCP<const double> locVals(localValues, rng.lbound()-localOffset,
00243 rng.size(), false);
00244
00245
00246 OrdType stride = 1;
00247
00248 sub_vec->initialize(rng.lbound(), rng.size(),
00249 locVals, stride);
00250
00251 }
00252
00253
00254
00255
00256 void SerialVector::releaseDetachedVectorViewImpl(
00257 RTOpPack::ConstSubVectorView<double>* sub_vec) const
00258 {
00259 int localOffset = 0;
00260 int localSubDim = globalDim_;
00261 if(
00262 sub_vec->globalOffset() < localOffset
00263 || localOffset+localSubDim < sub_vec->globalOffset()+sub_vec->subDim()
00264 )
00265 {
00266
00267 VectorDefaultBase<double>::releaseDetachedVectorViewImpl(sub_vec);
00268 return;
00269 }
00270
00271 sub_vec->uninitialize();
00272 }
00273
00274
00275
00276
00277 void SerialVector::acquireNonconstDetachedVectorViewImpl(
00278 const Teuchos::Range1D& rng_in,
00279 RTOpPack::SubVectorView<double>* sub_vec)
00280 {
00281 int localOffset = 0;
00282 int localSubDim = globalDim_;
00283
00284 if( rng_in == Range1D::Invalid ) {
00285
00286 sub_vec->initialize(rng_in.lbound(), 0, Teuchos::ArrayRCP<double>(), 1);
00287 return;
00288 }
00289
00290 const Range1D rng = validateRange(rng_in);
00291 if(
00292 rng.lbound() < localOffset
00293 ||
00294 localOffset+localSubDim-1 < rng.ubound()
00295 )
00296 {
00297
00298
00299 VectorDefaultBase<double>::acquireNonconstDetachedVectorViewImpl(rng_in,
00300 sub_vec);
00301 return;
00302 }
00303
00304
00305 double* localValues = &(data_[0]);
00306 Teuchos::ArrayRCP<double> locVals(localValues, rng.lbound()-localOffset,
00307
00308 rng.size(), false);
00309 OrdType stride = 1;
00310
00311 sub_vec->initialize(rng.lbound(), rng.size(),
00312 locVals, stride);
00313
00314 }
00315
00316
00317
00318 void SerialVector::commitNonconstDetachedVectorViewImpl(
00319 RTOpPack::SubVectorView<double>* sub_vec
00320 )
00321 {
00322 int localOffset = 0;
00323 int localSubDim = globalDim_;
00324 if(
00325 sub_vec->globalOffset() < localOffset
00326 ||
00327 localOffset+localSubDim < sub_vec->globalOffset()+sub_vec->subDim()
00328 )
00329 {
00330
00331 VectorDefaultBase<double>::commitNonconstDetachedVectorViewImpl(sub_vec);
00332 return;
00333 }
00334 sub_vec->uninitialize();
00335 }
00336
00337
00338
00339
00340 Teuchos::Range1D SerialVector::validateRange(const Teuchos::Range1D& rng_in) const
00341 {
00342 const Range1D rng = Teuchos::full_range(rng_in,0,globalDim_-1);
00343 TEST_FOR_EXCEPTION(
00344 !( 0 <= rng.lbound() && rng.ubound() < globalDim_ ), std::invalid_argument
00345 ,"SerialVector::validateRange(rowRng): Error, the range rng = ["
00346 <<rng.lbound()<<","<<rng.ubound()<<"] is not "
00347 "in the range [0,"<<(globalDim_-1)<<"]!"
00348 );
00349 return rng;
00350 }
00351
00352
00353
00354
00355
00356 double& SerialVector::operator[](OrdType globalIndex)
00357 {
00358 return data_[globalIndex];
00359 }
00360
00361 void SerialVector::setElement(OrdType index, const double& value)
00362 {
00363 data_[index] = value;
00364 }
00365
00366 void SerialVector::addToElement(OrdType index, const double& value)
00367 {
00368 data_[index] += value;
00369 }
00370
00371 const double& SerialVector::getElement(OrdType index) const
00372 {
00373 return data_[index];
00374 }
00375
00376 void SerialVector::getElements(const OrdType* globalIndices, int numElems,
00377 Teuchos::Array<double>& elems) const
00378 {
00379 elems.resize(numElems);
00380
00381 for (int i=0; i<numElems; i++)
00382 {
00383 elems[i] = data_[globalIndices[i]];
00384 }
00385 }
00386
00387 void SerialVector::setElements(int numElems, const int* globalIndices,
00388 const double* values)
00389 {
00390 for (int i=0; i<numElems; i++)
00391 {
00392 data_[globalIndices[i]] = values[i];
00393 }
00394 }
00395
00396 void SerialVector::addToElements(int numElems, const int* globalIndices,
00397 const double* values)
00398 {
00399 for (int i=0; i<numElems; i++)
00400 {
00401 data_[globalIndices[i]] += values[i];
00402 }
00403 }
00404
00405 const SerialVector* SerialVector::getConcrete(const Vector<double>& x)
00406 {
00407 const SerialVector* rtn = dynamic_cast<const SerialVector*>(x.ptr().get());
00408 TEST_FOR_EXCEPT(rtn==0);
00409 return rtn;
00410 }
00411
00412 SerialVector* SerialVector::getConcrete(Vector<double>& x)
00413 {
00414 SerialVector* rtn = dynamic_cast<SerialVector*>(x.ptr().get());
00415 TEST_FOR_EXCEPT(rtn==0);
00416 return rtn;
00417 }
00418
00419 void SerialVector::finalizeAssembly()
00420 {
00421
00422 }
00423
00424
00425 void SerialVector::print(std::ostream& os) const
00426 {
00427 for (int i=0; i<data_.size(); i++)
00428 {
00429 os << std::setw(5) << i << " " << std::setw(20) << data_[i] << std::endl;
00430 }
00431 }
00432
00433