FEI Version of the Day
fei_DirichletBCManager.cpp
00001 /*
00002 // @HEADER
00003 // ************************************************************************
00004 //             FEI: Finite Element Interface to Linear Solvers
00005 //                  Copyright (2005) Sandia Corporation.
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, the
00008 // 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 Alan Williams (william@sandia.gov) 
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 */
00042 
00043 
00044 #include <fei_iostream.hpp>
00045 #include <fei_sstream.hpp>
00046 #include <fei_DirichletBCManager.hpp>
00047 #include <fei_DirichletBCRecord.hpp>
00048 #include <fei_NodeDatabase.hpp>
00049 #include <fei_EqnBuffer.hpp>
00050 #include <fei_SharedPtr.hpp>
00051 #include <fei_VectorSpace.hpp>
00052 #include <fei_Matrix.hpp>
00053 
00054 #include <algorithm>
00055 #include <vector>
00056 
00057 typedef std::vector<fei::DirichletBCRecord> DBCvec;
00058 
00059 #undef fei_file
00060 #define fei_file "fei_DirichletBCManager.cpp"
00061 #include <fei_ErrMacros.hpp>
00062 
00063 namespace fei {
00064 
00065 int
00066 DirichletBCManager::getEqnNumber(int IDType, int ID, int fieldID, int offsetIntoField)
00067 {
00068   int eqn = -1;
00069   try {
00070     if (vecSpace_.get() != NULL) {
00071       vecSpace_->getGlobalIndex(IDType, ID, fieldID, eqn);
00072     }
00073     else {
00074       if (structure_ == NULL) {
00075         throw std::runtime_error("fei::DirichletBCManager has NULL SNL_FEI_Structure.");
00076       }
00077       NodeDatabase& nodeDB = structure_->getNodeDatabase();
00078       const NodeDescriptor* node = NULL;
00079       nodeDB.getNodeWithID(ID, node);
00080       if (node == NULL) {
00081         throw std::runtime_error("fei::DirichletBCManager::getEqnNumber failed to get node.");
00082       }
00083       node->getFieldEqnNumber(fieldID, eqn);
00084     }
00085   }
00086   catch(std::runtime_error& exc) {
00087     FEI_OSTRINGSTREAM osstr;
00088     osstr << "fei::DirichletBCManager::finalizeBCEqns caught exception: "
00089        << exc.what() << " BC IDType="<<IDType<<", ID="<<ID
00090        << ", fieldID="<<fieldID;
00091     fei::console_out() << osstr.str() << FEI_ENDL;
00092     ERReturn(-1);
00093   }
00094 
00095   return eqn + offsetIntoField;
00096 }
00097 
00098 void
00099 DirichletBCManager::addBCRecords(int numBCs,
00100                                  int IDType,
00101                                  int fieldID,
00102                                  int offsetIntoField,
00103                                  const int* IDs,
00104                                  const double* prescribedValues)
00105 {
00106   for(int i=0; i<numBCs; ++i) {
00107     int eqn = getEqnNumber(IDType, IDs[i], fieldID, offsetIntoField);
00108 
00109     bc_map::iterator iter = bcs_.lower_bound(eqn);
00110 
00111     if (iter == bcs_.end() || iter->first != eqn) {
00112       bcs_.insert(iter, std::make_pair(eqn, prescribedValues[i]));
00113       continue;
00114     }
00115     else iter->second = prescribedValues[i];
00116   }
00117 }
00118 
00119 void
00120 DirichletBCManager::addBCRecords(int numBCs,
00121                                  int IDType,
00122                                  int fieldID,
00123                                  const int* IDs,
00124                                  const int* offsetsIntoField,
00125                                  const double* prescribedValues)
00126 {
00127   for(int i=0; i<numBCs; ++i) {
00128     int eqn = getEqnNumber(IDType, IDs[i], fieldID, offsetsIntoField[i]);
00129 
00130     bc_map::iterator iter = bcs_.lower_bound(eqn);
00131 
00132     if (iter == bcs_.end() || iter->first != eqn) {
00133       bcs_.insert(iter, std::make_pair(eqn, prescribedValues[i]));
00134       continue;
00135     }
00136     else iter->second = prescribedValues[i];
00137   }
00138 }
00139 
00140 int
00141 DirichletBCManager::finalizeBCEqns(fei::Matrix& matrix,
00142                                    bool throw_if_bc_slave_conflict)
00143 {
00144   fei::SharedPtr<fei::Reducer> reducer = matrix.getMatrixGraph()->getReducer();
00145   bool haveSlaves = reducer.get()!=NULL;
00146 
00147   //copy the boundary-condition prescribed values into the matrix, in
00148   //an equation-number obtained by using the matrix' VectorSpace to map
00149   //from the BC's idtype,id,fieldID,component to an equation-number. The
00150   //bc values will go on the diagonal of the matrix, i.e., column-index
00151   //will be the same equation-number.
00152 
00153   bc_map::iterator iter = bcs_.begin(), iter_end = bcs_.end();
00154 
00155   for(; iter!=iter_end; ++iter) {
00156 
00157     int eqn = iter->first;
00158 
00159     if (haveSlaves) {
00160       if (reducer->isSlaveEqn(eqn)) {
00161         if (throw_if_bc_slave_conflict) {
00162           FEI_OSTRINGSTREAM osstr;
00163           osstr << "fei BCManager::finalizeBCeqns ERROR, eqn="<<eqn
00164             << " is both a BC eqn and slave-constraint eqn.";
00165           throw std::runtime_error(osstr.str());
00166         }
00167         continue;
00168       }
00169     }
00170 
00171     double* ptr = &iter->second;
00172 
00173     CHK_ERR( matrix.copyIn(1, &eqn, 1, &eqn, &ptr) );
00174   }
00175 
00176   bcs_.clear();
00177   return(0);
00178 }
00179 
00180 int
00181 DirichletBCManager::finalizeBCEqns(EqnBuffer& bcEqns)
00182 {
00183   //copy the boundary-condition prescribed values into bcEqns.
00184 
00185   bc_map::iterator iter = bcs_.begin(), iter_end = bcs_.end();
00186 
00187   for(; iter!=iter_end; ++iter) {
00188     int eqn = iter->first;
00189     double coef = iter->second;
00190 
00191     CHK_ERR( bcEqns.addEqn(eqn, &coef, &eqn, 1, false) );
00192   }
00193 
00194   bcs_.clear();
00195   return(0);
00196 }
00197 
00198 size_t
00199 DirichletBCManager::getNumBCRecords() const
00200 {
00201   return bcs_.size();
00202 }
00203 
00204 void
00205 DirichletBCManager::clearAllBCs()
00206 {
00207   bcs_.clear();
00208 }
00209 
00210 }//namespace fei
00211 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends