From 1f50d173d792695fdbb49ff438784ced1c8a200d Mon Sep 17 00:00:00 2001 From: vasiloglou Date: Sun, 16 Dec 2007 23:35:51 +0000 Subject: [PATCH] This is the first check in of the trilinos package --- fastlib/trilinos/.build.py.swp | Bin 0 -> 16384 bytes fastlib/trilinos/build.py | 74 + .../include/AnasaziBasicEigenproblem.hpp | 314 +++ .../include/AnasaziBasicOrthoManager.hpp | 893 +++++++ .../include/AnasaziBasicOutputManager.hpp | 170 ++ fastlib/trilinos/include/AnasaziBasicSort.hpp | 465 ++++ .../trilinos/include/AnasaziBlockDavidson.hpp | 1676 ++++++++++++ .../include/AnasaziBlockDavidsonSolMgr.hpp | 988 ++++++++ .../include/AnasaziBlockKrylovSchur.hpp | 1854 ++++++++++++++ .../include/AnasaziBlockKrylovSchurSolMgr.hpp | 634 +++++ .../trilinos/include/AnasaziConfigDefs.hpp | 188 ++ .../trilinos/include/AnasaziEigenproblem.hpp | 178 ++ .../trilinos/include/AnasaziEigensolver.hpp | 184 ++ .../include/AnasaziEigensolverDecl.hpp | 52 + .../trilinos/include/AnasaziEpetraAdapter.hpp | 800 ++++++ fastlib/trilinos/include/AnasaziLOBPCG.hpp | 2236 +++++++++++++++++ .../trilinos/include/AnasaziLOBPCGSolMgr.hpp | 797 ++++++ .../trilinos/include/AnasaziMVOPTester.hpp | 1477 +++++++++++ .../include/AnasaziMatOrthoManager.hpp | 421 ++++ fastlib/trilinos/include/AnasaziMultiVec.hpp | 371 +++ .../include/AnasaziMultiVecTraits.hpp | 216 ++ fastlib/trilinos/include/AnasaziOperator.hpp | 115 + .../include/AnasaziOperatorTraits.hpp | 92 + .../trilinos/include/AnasaziOrthoManager.hpp | 268 ++ .../trilinos/include/AnasaziOutputManager.hpp | 114 + .../include/AnasaziSVQBOrthoManager.hpp | 818 ++++++ .../include/AnasaziSimpleLOBPCGSolMgr.hpp | 398 +++ .../trilinos/include/AnasaziSolverManager.hpp | 90 + .../trilinos/include/AnasaziSolverUtils.hpp | 680 +++++ .../trilinos/include/AnasaziSortManager.hpp | 118 + .../trilinos/include/AnasaziStatusTest.hpp | 116 + .../include/AnasaziStatusTestCombo.hpp | 344 +++ .../include/AnasaziStatusTestDecl.hpp | 56 + .../include/AnasaziStatusTestMaxIters.hpp | 185 ++ .../AnasaziStatusTestOrderedResNorm.hpp | 377 +++ .../include/AnasaziStatusTestOutput.hpp | 221 ++ .../include/AnasaziStatusTestResNorm.hpp | 317 +++ fastlib/trilinos/include/AnasaziTypes.hpp | 153 ++ fastlib/trilinos/include/Anasazi_config.h | 214 ++ fastlib/trilinos/include/Epetra_BLAS.h | 166 ++ .../trilinos/include/Epetra_BLAS_wrappers.h | 266 ++ .../trilinos/include/Epetra_BasicDirectory.h | 176 ++ .../trilinos/include/Epetra_BasicRowMatrix.h | 508 ++++ fastlib/trilinos/include/Epetra_BlockMap.h | 535 ++++ .../trilinos/include/Epetra_BlockMapData.h | 105 + fastlib/trilinos/include/Epetra_CombineMode.h | 70 + fastlib/trilinos/include/Epetra_Comm.h | 366 +++ fastlib/trilinos/include/Epetra_CompObject.h | 111 + fastlib/trilinos/include/Epetra_ConfigDefs.h | 297 +++ fastlib/trilinos/include/Epetra_CrsGraph.h | 971 +++++++ .../trilinos/include/Epetra_CrsGraphData.h | 156 ++ fastlib/trilinos/include/Epetra_CrsMatrix.h | 1237 +++++++++ .../include/Epetra_CrsSingletonFilter.h | 303 +++ fastlib/trilinos/include/Epetra_Data.h | 94 + fastlib/trilinos/include/Epetra_DataAccess.h | 49 + fastlib/trilinos/include/Epetra_Directory.h | 99 + fastlib/trilinos/include/Epetra_DistObject.h | 270 ++ fastlib/trilinos/include/Epetra_Distributor.h | 177 ++ fastlib/trilinos/include/Epetra_Export.h | 300 +++ fastlib/trilinos/include/Epetra_FECrsGraph.h | 176 ++ fastlib/trilinos/include/Epetra_FECrsMatrix.h | 581 +++++ fastlib/trilinos/include/Epetra_FEVbrMatrix.h | 276 ++ fastlib/trilinos/include/Epetra_FEVector.h | 167 ++ fastlib/trilinos/include/Epetra_Flops.h | 94 + fastlib/trilinos/include/Epetra_HashTable.h | 131 + fastlib/trilinos/include/Epetra_Import.h | 308 +++ .../include/Epetra_IntSerialDenseMatrix.h | 395 +++ .../include/Epetra_IntSerialDenseVector.h | 289 +++ fastlib/trilinos/include/Epetra_IntVector.h | 291 +++ fastlib/trilinos/include/Epetra_InvOperator.h | 155 ++ fastlib/trilinos/include/Epetra_JadMatrix.h | 217 ++ fastlib/trilinos/include/Epetra_LAPACK.h | 402 +++ .../trilinos/include/Epetra_LAPACK_wrappers.h | 458 ++++ .../trilinos/include/Epetra_LinearProblem.h | 190 ++ fastlib/trilinos/include/Epetra_LocalMap.h | 115 + fastlib/trilinos/include/Epetra_Map.h | 214 ++ fastlib/trilinos/include/Epetra_MapColoring.h | 306 +++ fastlib/trilinos/include/Epetra_MultiVector.h | 1031 ++++++++ fastlib/trilinos/include/Epetra_Object.h | 197 ++ fastlib/trilinos/include/Epetra_OffsetIndex.h | 108 + fastlib/trilinos/include/Epetra_Operator.h | 134 + fastlib/trilinos/include/Epetra_RowMatrix.h | 257 ++ .../include/Epetra_RowMatrixTransposer.h | 154 ++ fastlib/trilinos/include/Epetra_SerialComm.h | 380 +++ .../trilinos/include/Epetra_SerialCommData.h | 65 + .../include/Epetra_SerialDenseMatrix.h | 529 ++++ .../include/Epetra_SerialDenseOperator.h | 120 + .../trilinos/include/Epetra_SerialDenseSVD.h | 507 ++++ .../include/Epetra_SerialDenseSolver.h | 422 ++++ .../include/Epetra_SerialDenseVector.h | 311 +++ .../include/Epetra_SerialDistributor.h | 133 + .../include/Epetra_SerialSpdDenseSolver.h | 265 ++ .../include/Epetra_SerialSymDenseMatrix.h | 270 ++ .../trilinos/include/Epetra_SrcDistObject.h | 64 + fastlib/trilinos/include/Epetra_Time.h | 117 + fastlib/trilinos/include/Epetra_Util.h | 290 +++ fastlib/trilinos/include/Epetra_VbrMatrix.h | 1379 ++++++++++ .../trilinos/include/Epetra_VbrRowMatrix.h | 236 ++ fastlib/trilinos/include/Epetra_Vector.h | 450 ++++ fastlib/trilinos/include/Epetra_Version.h | 33 + fastlib/trilinos/include/Epetra_config.h | 151 ++ .../trilinos/include/Makefile.export.anasazi | 55 + .../include/Makefile.export.anasazi.macros | 18 + .../trilinos/include/Makefile.export.epetra | 15 + .../include/Makefile.export.epetra.macros | 18 + .../trilinos/include/Makefile.export.teuchos | 71 + .../include/Makefile.export.teuchos.macros | 19 + .../include/Teuchos_AbstractFactory.hpp | 68 + .../include/Teuchos_AbstractFactoryStd.hpp | 205 ++ fastlib/trilinos/include/Teuchos_Array.hpp | 491 ++++ fastlib/trilinos/include/Teuchos_ArrayRCP.hpp | 746 ++++++ .../trilinos/include/Teuchos_ArrayRCPDecl.hpp | 970 +++++++ fastlib/trilinos/include/Teuchos_Assert.hpp | 77 + fastlib/trilinos/include/Teuchos_BLAS.hpp | 1867 ++++++++++++++ .../trilinos/include/Teuchos_BLAS_types.hpp | 67 + .../include/Teuchos_BLAS_wrappers.hpp | 466 ++++ .../trilinos/include/Teuchos_CTimeMonitor.h | 83 + fastlib/trilinos/include/Teuchos_Comm.hpp | 243 ++ .../trilinos/include/Teuchos_CommHelpers.hpp | 1003 ++++++++ .../include/Teuchos_CommUtilities.hpp | 45 + .../include/Teuchos_CommandLineProcessor.hpp | 606 +++++ .../trilinos/include/Teuchos_CompObject.hpp | 119 + .../include/Teuchos_CompileTimeAssert.hpp | 59 + .../trilinos/include/Teuchos_ConfigDefs.hpp | 157 ++ .../Teuchos_ConstNonconstObjectContainer.hpp | 114 + .../trilinos/include/Teuchos_DataAccess.hpp | 54 + .../trilinos/include/Teuchos_DefaultComm.hpp | 110 + .../include/Teuchos_DefaultSerialComm.hpp | 226 ++ .../trilinos/include/Teuchos_Describable.hpp | 242 ++ .../trilinos/include/Teuchos_ErrorPolling.hpp | 115 + .../include/Teuchos_ExpatHandlerAdapter.hpp | 64 + .../trilinos/include/Teuchos_F77_wrappers.h | 117 + .../trilinos/include/Teuchos_FILEstream.hpp | 76 + .../trilinos/include/Teuchos_FancyOStream.hpp | 1256 +++++++++ .../include/Teuchos_FileInputSource.hpp | 63 + .../include/Teuchos_FileInputStream.hpp | 66 + fastlib/trilinos/include/Teuchos_Flops.hpp | 125 + .../include/Teuchos_GlobalMPISession.hpp | 128 + fastlib/trilinos/include/Teuchos_Handle.hpp | 187 ++ .../trilinos/include/Teuchos_Handleable.hpp | 127 + fastlib/trilinos/include/Teuchos_HashSet.hpp | 263 ++ .../trilinos/include/Teuchos_HashUtils.hpp | 121 + .../trilinos/include/Teuchos_Hashtable.hpp | 332 +++ fastlib/trilinos/include/Teuchos_LAPACK.hpp | 2219 ++++++++++++++++ .../include/Teuchos_LAPACK_wrappers.hpp | 771 ++++++ .../include/Teuchos_LabeledObject.hpp | 73 + .../include/Teuchos_Libxml2HandlerAdapter.hpp | 64 + fastlib/trilinos/include/Teuchos_MPIComm.hpp | 174 ++ .../include/Teuchos_MPIContainerComm.hpp | 711 ++++++ .../trilinos/include/Teuchos_MPISession.hpp | 74 + .../trilinos/include/Teuchos_MPITraits.hpp | 102 + fastlib/trilinos/include/Teuchos_Object.hpp | 179 ++ .../include/Teuchos_OpaqueWrapper.hpp | 195 ++ .../include/Teuchos_OrdinalTraits.hpp | 124 + .../include/Teuchos_ParameterEntry.hpp | 352 +++ .../Teuchos_ParameterEntryValidator.hpp | 129 + .../include/Teuchos_ParameterList.hpp | 1112 ++++++++ .../include/Teuchos_ParameterListAcceptor.hpp | 127 + ...uchos_ParameterListAcceptorDefaultBase.hpp | 118 + .../Teuchos_ParameterListExceptions.hpp | 69 + .../Teuchos_ParameterListNonAcceptor.hpp | 66 + .../Teuchos_ParameterXMLFileReader.hpp | 56 + .../Teuchos_PerformanceMonitorBase.hpp | 146 ++ .../Teuchos_PerformanceMonitorUtils.hpp | 113 + .../trilinos/include/Teuchos_Polynomial.hpp | 187 ++ .../include/Teuchos_PolynomialDecl.hpp | 153 ++ .../include/Teuchos_PolynomialTraits.hpp | 79 + .../include/Teuchos_PrimitiveTypeTraits.hpp | 172 ++ .../include/Teuchos_PromotionTraits.hpp | 76 + fastlib/trilinos/include/Teuchos_RCP.hpp | 602 +++++ .../Teuchos_RCPBoostSharedPtrConversions.hpp | 63 + ...uchos_RCPBoostSharedPtrConversionsDecl.hpp | 121 + fastlib/trilinos/include/Teuchos_RCPDecl.hpp | 1184 +++++++++ fastlib/trilinos/include/Teuchos_Range1D.hpp | 313 +++ .../trilinos/include/Teuchos_RawMPITraits.hpp | 169 ++ .../trilinos/include/Teuchos_ReductionOp.hpp | 70 + .../include/Teuchos_ReductionOpHelpers.hpp | 156 ++ .../trilinos/include/Teuchos_RefCountPtr.hpp | 35 + .../include/Teuchos_RefCountPtrDecl.hpp | 39 + .../trilinos/include/Teuchos_ScalarTraits.hpp | 601 +++++ .../include/Teuchos_SerialDenseMatrix.hpp | 895 +++++++ .../include/Teuchos_SerialDenseVector.hpp | 287 +++ .../include/Teuchos_SerializationTraits.hpp | 216 ++ .../Teuchos_SerializationTraitsHelpers.hpp | 311 +++ .../trilinos/include/Teuchos_Serializer.hpp | 113 + .../include/Teuchos_SerializerHelpers.hpp | 337 +++ .../include/Teuchos_StandardCatchMacros.hpp | 92 + .../Teuchos_StandardCompositionMacros.hpp | 156 ++ ...euchos_StandardMemberCompositionMacros.hpp | 87 + ...uchos_StandardParameterEntryValidators.hpp | 1143 +++++++++ fastlib/trilinos/include/Teuchos_StrUtils.hpp | 146 ++ .../include/Teuchos_StringInputSource.hpp | 68 + .../include/Teuchos_StringInputStream.hpp | 73 + .../include/Teuchos_StringToIntMap.hpp | 151 ++ .../trilinos/include/Teuchos_TableColumn.hpp | 78 + .../trilinos/include/Teuchos_TableEntry.hpp | 163 ++ .../trilinos/include/Teuchos_TableFormat.hpp | 171 ++ .../include/Teuchos_TestForException.hpp | 222 ++ fastlib/trilinos/include/Teuchos_Time.hpp | 131 + .../trilinos/include/Teuchos_TimeMonitor.hpp | 169 ++ .../Teuchos_TreeBuildingXMLHandler.hpp | 86 + .../include/Teuchos_TypeNameTraits.hpp | 144 ++ fastlib/trilinos/include/Teuchos_Utils.hpp | 114 + .../include/Teuchos_VerboseObject.hpp | 411 +++ ...chos_VerboseObjectParameterListHelpers.hpp | 138 + .../include/Teuchos_VerbosityLevel.hpp | 103 + ...bosityLevelCommandLineProcessorHelpers.hpp | 57 + fastlib/trilinos/include/Teuchos_Version.hpp | 43 + .../trilinos/include/Teuchos_Workspace.hpp | 473 ++++ .../include/Teuchos_XMLInputSource.hpp | 78 + .../include/Teuchos_XMLInputStream.hpp | 62 + .../trilinos/include/Teuchos_XMLObject.hpp | 201 ++ .../include/Teuchos_XMLObjectImplem.hpp | 125 + .../Teuchos_XMLParameterListHelpers.hpp | 101 + .../Teuchos_XMLParameterListReader.hpp | 64 + .../Teuchos_XMLParameterListWriter.hpp | 66 + .../trilinos/include/Teuchos_XMLParser.hpp | 133 + fastlib/trilinos/include/Teuchos_any.hpp | 331 +++ fastlib/trilinos/include/Teuchos_arrayArg.hpp | 249 ++ fastlib/trilinos/include/Teuchos_as.hpp | 175 ++ .../Teuchos_basic_oblackholestream.hpp | 56 + fastlib/trilinos/include/Teuchos_config.h | 240 ++ fastlib/trilinos/include/Teuchos_dyn_cast.hpp | 169 ++ fastlib/trilinos/include/Teuchos_exit.h | 89 + fastlib/trilinos/include/Teuchos_getConst.hpp | 52 + .../include/Teuchos_implicit_cast.hpp | 141 ++ fastlib/trilinos/include/Teuchos_map.hpp | 153 ++ .../include/Teuchos_oblackholestream.hpp | 41 + fastlib/trilinos/include/Trilinos_version.h | 61 + .../trilinos/include/strip_dup_incl_paths.pl | 44 + fastlib/trilinos/include/strip_dup_libs.pl | 69 + fastlib/trilinos/test.cc | 75 + 232 files changed, 68889 insertions(+) create mode 100644 fastlib/trilinos/.build.py.swp create mode 100644 fastlib/trilinos/build.py create mode 100644 fastlib/trilinos/include/AnasaziBasicEigenproblem.hpp create mode 100644 fastlib/trilinos/include/AnasaziBasicOrthoManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziBasicOutputManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziBasicSort.hpp create mode 100644 fastlib/trilinos/include/AnasaziBlockDavidson.hpp create mode 100644 fastlib/trilinos/include/AnasaziBlockDavidsonSolMgr.hpp create mode 100644 fastlib/trilinos/include/AnasaziBlockKrylovSchur.hpp create mode 100644 fastlib/trilinos/include/AnasaziBlockKrylovSchurSolMgr.hpp create mode 100644 fastlib/trilinos/include/AnasaziConfigDefs.hpp create mode 100644 fastlib/trilinos/include/AnasaziEigenproblem.hpp create mode 100644 fastlib/trilinos/include/AnasaziEigensolver.hpp create mode 100644 fastlib/trilinos/include/AnasaziEigensolverDecl.hpp create mode 100644 fastlib/trilinos/include/AnasaziEpetraAdapter.hpp create mode 100644 fastlib/trilinos/include/AnasaziLOBPCG.hpp create mode 100644 fastlib/trilinos/include/AnasaziLOBPCGSolMgr.hpp create mode 100644 fastlib/trilinos/include/AnasaziMVOPTester.hpp create mode 100644 fastlib/trilinos/include/AnasaziMatOrthoManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziMultiVec.hpp create mode 100644 fastlib/trilinos/include/AnasaziMultiVecTraits.hpp create mode 100644 fastlib/trilinos/include/AnasaziOperator.hpp create mode 100644 fastlib/trilinos/include/AnasaziOperatorTraits.hpp create mode 100644 fastlib/trilinos/include/AnasaziOrthoManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziOutputManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziSVQBOrthoManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziSimpleLOBPCGSolMgr.hpp create mode 100644 fastlib/trilinos/include/AnasaziSolverManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziSolverUtils.hpp create mode 100644 fastlib/trilinos/include/AnasaziSortManager.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTest.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTestCombo.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTestDecl.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTestMaxIters.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTestOrderedResNorm.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTestOutput.hpp create mode 100644 fastlib/trilinos/include/AnasaziStatusTestResNorm.hpp create mode 100644 fastlib/trilinos/include/AnasaziTypes.hpp create mode 100644 fastlib/trilinos/include/Anasazi_config.h create mode 100644 fastlib/trilinos/include/Epetra_BLAS.h create mode 100644 fastlib/trilinos/include/Epetra_BLAS_wrappers.h create mode 100644 fastlib/trilinos/include/Epetra_BasicDirectory.h create mode 100644 fastlib/trilinos/include/Epetra_BasicRowMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_BlockMap.h create mode 100644 fastlib/trilinos/include/Epetra_BlockMapData.h create mode 100644 fastlib/trilinos/include/Epetra_CombineMode.h create mode 100644 fastlib/trilinos/include/Epetra_Comm.h create mode 100644 fastlib/trilinos/include/Epetra_CompObject.h create mode 100644 fastlib/trilinos/include/Epetra_ConfigDefs.h create mode 100644 fastlib/trilinos/include/Epetra_CrsGraph.h create mode 100644 fastlib/trilinos/include/Epetra_CrsGraphData.h create mode 100644 fastlib/trilinos/include/Epetra_CrsMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_CrsSingletonFilter.h create mode 100644 fastlib/trilinos/include/Epetra_Data.h create mode 100644 fastlib/trilinos/include/Epetra_DataAccess.h create mode 100644 fastlib/trilinos/include/Epetra_Directory.h create mode 100644 fastlib/trilinos/include/Epetra_DistObject.h create mode 100644 fastlib/trilinos/include/Epetra_Distributor.h create mode 100644 fastlib/trilinos/include/Epetra_Export.h create mode 100644 fastlib/trilinos/include/Epetra_FECrsGraph.h create mode 100644 fastlib/trilinos/include/Epetra_FECrsMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_FEVbrMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_FEVector.h create mode 100644 fastlib/trilinos/include/Epetra_Flops.h create mode 100644 fastlib/trilinos/include/Epetra_HashTable.h create mode 100644 fastlib/trilinos/include/Epetra_Import.h create mode 100644 fastlib/trilinos/include/Epetra_IntSerialDenseMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_IntSerialDenseVector.h create mode 100644 fastlib/trilinos/include/Epetra_IntVector.h create mode 100644 fastlib/trilinos/include/Epetra_InvOperator.h create mode 100644 fastlib/trilinos/include/Epetra_JadMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_LAPACK.h create mode 100644 fastlib/trilinos/include/Epetra_LAPACK_wrappers.h create mode 100644 fastlib/trilinos/include/Epetra_LinearProblem.h create mode 100644 fastlib/trilinos/include/Epetra_LocalMap.h create mode 100644 fastlib/trilinos/include/Epetra_Map.h create mode 100644 fastlib/trilinos/include/Epetra_MapColoring.h create mode 100644 fastlib/trilinos/include/Epetra_MultiVector.h create mode 100644 fastlib/trilinos/include/Epetra_Object.h create mode 100644 fastlib/trilinos/include/Epetra_OffsetIndex.h create mode 100644 fastlib/trilinos/include/Epetra_Operator.h create mode 100644 fastlib/trilinos/include/Epetra_RowMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_RowMatrixTransposer.h create mode 100644 fastlib/trilinos/include/Epetra_SerialComm.h create mode 100644 fastlib/trilinos/include/Epetra_SerialCommData.h create mode 100644 fastlib/trilinos/include/Epetra_SerialDenseMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_SerialDenseOperator.h create mode 100644 fastlib/trilinos/include/Epetra_SerialDenseSVD.h create mode 100644 fastlib/trilinos/include/Epetra_SerialDenseSolver.h create mode 100644 fastlib/trilinos/include/Epetra_SerialDenseVector.h create mode 100644 fastlib/trilinos/include/Epetra_SerialDistributor.h create mode 100644 fastlib/trilinos/include/Epetra_SerialSpdDenseSolver.h create mode 100644 fastlib/trilinos/include/Epetra_SerialSymDenseMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_SrcDistObject.h create mode 100644 fastlib/trilinos/include/Epetra_Time.h create mode 100644 fastlib/trilinos/include/Epetra_Util.h create mode 100644 fastlib/trilinos/include/Epetra_VbrMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_VbrRowMatrix.h create mode 100644 fastlib/trilinos/include/Epetra_Vector.h create mode 100644 fastlib/trilinos/include/Epetra_Version.h create mode 100644 fastlib/trilinos/include/Epetra_config.h create mode 100644 fastlib/trilinos/include/Makefile.export.anasazi create mode 100644 fastlib/trilinos/include/Makefile.export.anasazi.macros create mode 100644 fastlib/trilinos/include/Makefile.export.epetra create mode 100644 fastlib/trilinos/include/Makefile.export.epetra.macros create mode 100644 fastlib/trilinos/include/Makefile.export.teuchos create mode 100644 fastlib/trilinos/include/Makefile.export.teuchos.macros create mode 100644 fastlib/trilinos/include/Teuchos_AbstractFactory.hpp create mode 100644 fastlib/trilinos/include/Teuchos_AbstractFactoryStd.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Array.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ArrayRCP.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ArrayRCPDecl.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Assert.hpp create mode 100644 fastlib/trilinos/include/Teuchos_BLAS.hpp create mode 100644 fastlib/trilinos/include/Teuchos_BLAS_types.hpp create mode 100644 fastlib/trilinos/include/Teuchos_BLAS_wrappers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_CTimeMonitor.h create mode 100644 fastlib/trilinos/include/Teuchos_Comm.hpp create mode 100644 fastlib/trilinos/include/Teuchos_CommHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_CommUtilities.hpp create mode 100644 fastlib/trilinos/include/Teuchos_CommandLineProcessor.hpp create mode 100644 fastlib/trilinos/include/Teuchos_CompObject.hpp create mode 100644 fastlib/trilinos/include/Teuchos_CompileTimeAssert.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ConfigDefs.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ConstNonconstObjectContainer.hpp create mode 100644 fastlib/trilinos/include/Teuchos_DataAccess.hpp create mode 100644 fastlib/trilinos/include/Teuchos_DefaultComm.hpp create mode 100644 fastlib/trilinos/include/Teuchos_DefaultSerialComm.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Describable.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ErrorPolling.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ExpatHandlerAdapter.hpp create mode 100644 fastlib/trilinos/include/Teuchos_F77_wrappers.h create mode 100644 fastlib/trilinos/include/Teuchos_FILEstream.hpp create mode 100644 fastlib/trilinos/include/Teuchos_FancyOStream.hpp create mode 100644 fastlib/trilinos/include/Teuchos_FileInputSource.hpp create mode 100644 fastlib/trilinos/include/Teuchos_FileInputStream.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Flops.hpp create mode 100644 fastlib/trilinos/include/Teuchos_GlobalMPISession.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Handle.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Handleable.hpp create mode 100644 fastlib/trilinos/include/Teuchos_HashSet.hpp create mode 100644 fastlib/trilinos/include/Teuchos_HashUtils.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Hashtable.hpp create mode 100644 fastlib/trilinos/include/Teuchos_LAPACK.hpp create mode 100644 fastlib/trilinos/include/Teuchos_LAPACK_wrappers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_LabeledObject.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Libxml2HandlerAdapter.hpp create mode 100644 fastlib/trilinos/include/Teuchos_MPIComm.hpp create mode 100644 fastlib/trilinos/include/Teuchos_MPIContainerComm.hpp create mode 100644 fastlib/trilinos/include/Teuchos_MPISession.hpp create mode 100644 fastlib/trilinos/include/Teuchos_MPITraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Object.hpp create mode 100644 fastlib/trilinos/include/Teuchos_OpaqueWrapper.hpp create mode 100644 fastlib/trilinos/include/Teuchos_OrdinalTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterEntry.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterEntryValidator.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterList.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterListAcceptor.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterListAcceptorDefaultBase.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterListExceptions.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterListNonAcceptor.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ParameterXMLFileReader.hpp create mode 100644 fastlib/trilinos/include/Teuchos_PerformanceMonitorBase.hpp create mode 100644 fastlib/trilinos/include/Teuchos_PerformanceMonitorUtils.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Polynomial.hpp create mode 100644 fastlib/trilinos/include/Teuchos_PolynomialDecl.hpp create mode 100644 fastlib/trilinos/include/Teuchos_PolynomialTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_PrimitiveTypeTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_PromotionTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RCP.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RCPBoostSharedPtrConversions.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RCPBoostSharedPtrConversionsDecl.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RCPDecl.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Range1D.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RawMPITraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ReductionOp.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ReductionOpHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RefCountPtr.hpp create mode 100644 fastlib/trilinos/include/Teuchos_RefCountPtrDecl.hpp create mode 100644 fastlib/trilinos/include/Teuchos_ScalarTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_SerialDenseMatrix.hpp create mode 100644 fastlib/trilinos/include/Teuchos_SerialDenseVector.hpp create mode 100644 fastlib/trilinos/include/Teuchos_SerializationTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_SerializationTraitsHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Serializer.hpp create mode 100644 fastlib/trilinos/include/Teuchos_SerializerHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StandardCatchMacros.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StandardCompositionMacros.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StandardMemberCompositionMacros.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StandardParameterEntryValidators.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StrUtils.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StringInputSource.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StringInputStream.hpp create mode 100644 fastlib/trilinos/include/Teuchos_StringToIntMap.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TableColumn.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TableEntry.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TableFormat.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TestForException.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Time.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TimeMonitor.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TreeBuildingXMLHandler.hpp create mode 100644 fastlib/trilinos/include/Teuchos_TypeNameTraits.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Utils.hpp create mode 100644 fastlib/trilinos/include/Teuchos_VerboseObject.hpp create mode 100644 fastlib/trilinos/include/Teuchos_VerboseObjectParameterListHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_VerbosityLevel.hpp create mode 100644 fastlib/trilinos/include/Teuchos_VerbosityLevelCommandLineProcessorHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Version.hpp create mode 100644 fastlib/trilinos/include/Teuchos_Workspace.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLInputSource.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLInputStream.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLObject.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLObjectImplem.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLParameterListHelpers.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLParameterListReader.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLParameterListWriter.hpp create mode 100644 fastlib/trilinos/include/Teuchos_XMLParser.hpp create mode 100644 fastlib/trilinos/include/Teuchos_any.hpp create mode 100644 fastlib/trilinos/include/Teuchos_arrayArg.hpp create mode 100644 fastlib/trilinos/include/Teuchos_as.hpp create mode 100644 fastlib/trilinos/include/Teuchos_basic_oblackholestream.hpp create mode 100644 fastlib/trilinos/include/Teuchos_config.h create mode 100644 fastlib/trilinos/include/Teuchos_dyn_cast.hpp create mode 100644 fastlib/trilinos/include/Teuchos_exit.h create mode 100644 fastlib/trilinos/include/Teuchos_getConst.hpp create mode 100644 fastlib/trilinos/include/Teuchos_implicit_cast.hpp create mode 100644 fastlib/trilinos/include/Teuchos_map.hpp create mode 100644 fastlib/trilinos/include/Teuchos_oblackholestream.hpp create mode 100644 fastlib/trilinos/include/Trilinos_version.h create mode 100755 fastlib/trilinos/include/strip_dup_incl_paths.pl create mode 100755 fastlib/trilinos/include/strip_dup_libs.pl create mode 100644 fastlib/trilinos/test.cc diff --git a/fastlib/trilinos/.build.py.swp b/fastlib/trilinos/.build.py.swp new file mode 100644 index 0000000000000000000000000000000000000000..03915f6cdf64b637a5d6e2a2a00519afdcf9794f GIT binary patch literal 16384 zcmeHNO^h5z6|MwKGW;cq14ubldWk)=%=DNT2-zq|i`hh$H*w_MK*DAk*rTms^P#P|AdXLfoPV}s>L z)!J`orn`P#ef8d}_o}*o>a%B`;Gb|$GhBBw_SK)r$B%vGb@uxSV?#51==8%LJvs79 zl&6J}iR*dp5MR8JEB$n_%9o1mF*qNfMwu@ z894pmM^8~BE6)A=_&rbGaC^1^%YbFTGGH073|Iy%1C{~HfMwwA!+?ozXU{|2+Y6Cb zi_hB*eZHgk&5O^E9C}{-v>%oM%YbFTGGH073|Iy%1C{~HfMvikU>UFs+=2`UpRudQ z7<>L*5Dw@6W&Z!WyBPZ(@Lk{=z(rsO_#p5B;E(TT>_y-L@VECd_G{pqfCqGdH{Z+H zOTg!W4*{>fhp~O&A>fsFGxjy$6!6amW4{6tU;}V~W5AntGWJ8D58MsBaR+1H2Zq4C zz#EX4Wd0QJFUbEI@NK{Y9s%wF{`^kd2fhP54BQD^#YVMH`CfOCI?7wG*mz_1fGYBHT>8#D& zZtZ?4A5tm#EGKQ|rHN7FLUhixG^vjGPIG%2>t2l3(Rdd^JpD{>YvaP%_04k9xqE$ms(6Yn zi@D6yhv%Bb2bea@y5hxqILpME8Gx2}ugB*?d!t}qF00`A7z96Y0_8Z3hp)Pdgl{e| z)+Q1U&6i8F-vXJ9>bmZV5TK*CauEcHK#lUbi;7$#oe_~p#O1&hB>8hk6f`o0?j--Y zAZ);BQI@OIr;Mrj>4qe^0CnX_|7O&$o;lW783Y=3Jdu1P_F>ct#xhp;CZZ`(TwdM&ZYob}T6bUx{xaz8dV38ekt_ zbYvv@q3jfPpPPK~w0cih7El6Sr`vD=T|44HLg*|>#9~-Rn9Z5AKS&NnOMh`=|^3cWJ%*aERMVr^I1jX zG)0S(TsxLZ@$yh*ETHM+Q4%sn5%O^mr3hU3QppY)cuZ+NR+_xgKOYuot=-uDTJg79Fis!LLttgms`y>$hvN@ zYExVmAdZ8B_7$w!@Fb06g#Znz1+{?tg{hVLaSg40PQqQ^ zI=FW9_$Y8XlZAe>+QBnlS`K!pG?}K5YM5;Gy<9G7OV;^vbQC*Q(LtT&R+@I50oukT ztk<5Q5p88rbwz9*ELF-c5=^T>9DfkBlV$g+c+i1@@#+^vhtTX5{zRs>aJn>~6BV5_ zya*|=GH0s_?;{oCrI(!O+4?RUERX|NEP}4cLvGG)8 zam1f1C>5gUl0NsOj$}yRD$%LgS#3a@Srof7pI_{{3FZ)8lh3voJaBEk(kz8) z=S{UK{Q+UEwLIHNb%m)By|I9jQll=T{Qo}W;lBVV|3|8qU00FgOW?!6TgdT$30wiTfK}i& z;7`c&e+*m!T;R9J^M3^F1M9%Oz;WOX;IGL0e+qmZcma48cm_BRd>ptBcndPTT*xBv zd4goJmu0{*U>UFsSOzQumI2Ga|BHbmjxDf#awA6?H&}h~MC55t{9$dG;xyVsdgfYI| zk4cE@ayLFZ4w>B_r9+J@qdzz(3B&(#tDg4g9t)x%8DWbs-$TL10QNbs2|BwukIm?R E11qc7kN^Mx literal 0 HcmV?d00001 diff --git a/fastlib/trilinos/build.py b/fastlib/trilinos/build.py new file mode 100644 index 0000000000..aae398013f --- /dev/null +++ b/fastlib/trilinos/build.py @@ -0,0 +1,74 @@ +# Scroll down to see the main part. +# (This first part is dedicated to compiling and installing LAPACK.) + +wgetrule( + name = "trilinos_tgz", + type = Types.ANY, + url = "http://www.cc.gatech.edu/~gtg739c/trilinos-8.0.4.tar.gz") + +def gen_compile_trilinos(sysentry, files, params): + trilinos_tgz = files["trilinos_tgz"].single(Types.ANY) + libtrilinospack = sysentry.file("KEEP/trilinospack.a", "arch", "kernel", "compiler") + workspace_dir = os.path.join(os.path.dirname(libtrilinospack.name), "libtrilinospack_workspace") + compiler_info = compilers[params["compiler"]] + compiler = compiler_info.compiler_program("f") + # Make sure we won't rm -rf anything bad + assert "libtrilinospack_workspace" in workspace_dir + sysentry.command("echo '... Extracting Source trilinos files...'") + sysentry.command("mkdir -p %s" % sq(workspace_dir)) + sysentry.command("cd %s && tar -xzf %s" % (sq(workspace_dir), sq(trilinos_tgz.name))) + sysentry.command("echo '*** Compiling Trilinos 8.0.4 version.'") + sysentry.command("echo '... We only compile Epetra, Teuchos, Anasazi:'") + sysentry.command("echo '... At this time we do not support distributed trilinos.'") + sysentry.command("echo '... Only serial version is built.'") + sysentry.command("echo '... For more information see http://trilinos.sandia.gov/Trilinos8.0Tutorial.pdf'") + sysentry.command("echo '... This may take several minutes .'") + sysentry.command("cd %s/trilinos-8.0.4 && mkdir -p LINUX_SERIAL " % sq(workspace_dir)) + sysentry.command("echo '***Configuring Trilinos...'") + sysentry.command("cd %s/trilinos-8.0.4/LINUX_SERIAL && \ + ../configure --prefix=%s/trilinos-8.0.4/LINUX_SERIAL \ + --disable-default-packages \ + --enable-epetra \ + --enable-teuchos \ + --enable-anasazi \ + | tee configure_LINUX_SERIAL.log" % (sq(workspace_dir) , + sq(workspace_dir))) + sysentry.command("echo '...Configuration Done, if you encountered errors check\ + logfile configure_LINUX_SERIAL.log'") + sysentry.command("echo '*** Ready to compile now'"); + sysentry.command("cd %s/trilinos-8.0.4/LINUX_SERIAL && \ + make everything| tee make_LINUX_SERIAL.log" % (sq(workspace_dir))) + sysentry.command("cd %s/trilinos-8.0.4/LINUX_SERIAL && \ + make install | tee make_install.LINUX_SERIAL.log" % (sq(workspace_dir))) + sysentry.command("echo '*** Finished compiling, for errors check \ + logfile make_LINUX_SERIAL.log and make_install_LINUX_SERIAL.log'") + #we have to find out how to combine all libraries into one but + #first we have to remove any old libtrilinos.a + sysentry.command("rm -f %s" % sq(libtrilinospack.name)) + sysentry.command("cd %s/trilinos-8.0.4/LINUX_SERIAL/lib && \ + ar -x libepetra.a && \ + ar -x libteuchos.a && \ + ar -x libanasazi.a && \ + ar -rS %s *.o" % + (sq(workspace_dir), sq(libtrilinospack.name))) + sysentry.command("echo '... Created archive'") + sysentry.command("echo '... Copying the include header files to fastlib'") + sysentry.command("cp -r %s/trilinos-8.0.4/LINUX_SERIAL/include ." % sq(workspace_dir)) + sysentry.command("echo '... Cleaning'") + #sysentry.command("rm -rf %s" % sq(workspace_dir)) + sysentry.command("echo '*** Done with TRILINOS!'") + return [(Types.LINKABLE, libtrilinospack)] + +customrule( + name = "libtrilinos", + dependencies = {"trilinos_tgz": [find(":trilinos_tgz")]}, + doit_fn = gen_compile_trilinos) + +#---- This is the test part of the installation + +binrule( + name = "test_trilinos", + sources = ["test.cc"], + headers = lglob("./include/*.hpp"), + deplibs = ["base:base", "la:libblaspack", ":libtrilinos"]) + diff --git a/fastlib/trilinos/include/AnasaziBasicEigenproblem.hpp b/fastlib/trilinos/include/AnasaziBasicEigenproblem.hpp new file mode 100644 index 0000000000..05e1582238 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziBasicEigenproblem.hpp @@ -0,0 +1,314 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_BASIC_EIGENPROBLEM_H +#define ANASAZI_BASIC_EIGENPROBLEM_H + +/*! \file AnasaziBasicEigenproblem.hpp + \brief Basic implementation of the Anasazi::Eigenproblem class +*/ + +#include "AnasaziEigenproblem.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" + +/*! \class Anasazi::BasicEigenproblem + \brief This provides a basic implementation for defining standard or + generalized eigenvalue problems. +*/ + +namespace Anasazi { + + template + class BasicEigenproblem : public virtual Eigenproblem { + + public: + + //! @name Constructors/Destructor + //@{ + + //! Empty constructor - allows Anasazi::BasicEigenproblem to be described at a later time through "Set Methods". + BasicEigenproblem(); + + //! Standard Eigenvalue Problem Constructor. + BasicEigenproblem( const Teuchos::RCP& Op, const Teuchos::RCP& InitVec ); + + //! Generalized Eigenvalue Problem Constructor. + BasicEigenproblem( const Teuchos::RCP& Op, const Teuchos::RCP& B, const Teuchos::RCP& InitVec ); + + //! Copy Constructor. + BasicEigenproblem( const BasicEigenproblem& Problem ); + + //! Destructor. + virtual ~BasicEigenproblem() {}; + //@} + + //! @name Set Methods + //@{ + + /*! \brief Set the operator for which eigenvalues will be computed. + + \note This may be different from the \c A if a spectral transformation is employed. + For example, this operator may apply the operation \f$(A-\sigma I)^{-1}\f$ if you are + looking for eigenvalues of \c A around \f$\sigma\f$. + */ + void setOperator( const Teuchos::RCP& Op ) { _Op = Op; _isSet=false; }; + + /*! \brief Set the operator \c A of the eigenvalue problem \f$Ax=Mx\lambda\f$. + */ + void setA( const Teuchos::RCP& A ) { _AOp = A; _isSet=false; }; + + /*! \brief Set the operator \c M of the eigenvalue problem \f$Ax = Mx\lambda\f$. + */ + void setM( const Teuchos::RCP& M ) { _MOp = M; _isSet=false; }; + + /*! \brief Set the preconditioner for this eigenvalue problem \f$Ax = Mx\lambda\f$. + */ + void setPrec( const Teuchos::RCP& Prec ) { _Prec = Prec; _isSet=false; }; + + /*! \brief Set the initial guess. + + This vector is required to create all the space needed + by Anasazi to solve the eigenvalue problem. + + \note Even if an initial guess is not known by the user, an initial vector must be passed in. + */ + void setInitVec( const Teuchos::RCP& InitVec ) { _InitVec = InitVec; _isSet=false; }; + + /*! \brief Set auxiliary vectors. + + \note This multivector can have any number of columns, and most likely will contain vectors that + will be used by the eigensolver to orthogonalize against. + */ + void setAuxVecs( const Teuchos::RCP& AuxVecs ) { _AuxVecs = AuxVecs; _isSet=false; }; + + //! Specify the number of eigenvalues (NEV) that are requested. + void setNEV( int nev ){ _nev = nev; _isSet=false; }; + + //! Specify the symmetry of this eigenproblem. + /*! This knowledge may allow the solver to take advantage of the eigenproblems' symmetry. + Some computational work can be avoided by setting this properly. + */ + void setHermitian( bool isSym ){ _isSym = isSym; _isSet=false; }; + + /*! \brief Specify that this eigenproblem is fully defined. + * + * This routine serves multiple purpose: + * - sanity check that the eigenproblem has been fully and consistently defined + * - opportunity for the eigenproblem to allocate internal storage for eigenvalues + * and eigenvectors (to be used by eigensolvers and solver managers) + * + * + * This method reallocates internal storage, so that any previously retrieved references to + * internal storage (eigenvectors or eigenvalues) are invalidated. + * + * \note The user MUST call this routine before they send the eigenproblem to any solver or solver manager. + * + * \returns \c true signifies success, \c false signifies error. + */ + bool setProblem(); + + /*! \brief Set the solution to the eigenproblem. + * + * This mechanism allows an Eigensolution struct to be associated with an Eigenproblem object. + * setSolution() is usually called by a solver manager at the end of its SolverManager::solve() + * routine. + */ + void setSolution(const Eigensolution &sol) {_sol = sol;} + + //@} + + //! @name Accessor Methods + //@{ + + //! Get a pointer to the operator for which eigenvalues will be computed. + Teuchos::RCP getOperator() const { return( _Op ); }; + + //! Get a pointer to the operator \c A of the eigenproblem \f$Ax=\lambda Mx\f$. + Teuchos::RCP getA() const { return( _AOp ); }; + + //! Get a pointer to the operator \c M of the eigenproblem \f$Ax=\lambda Mx\f$. + Teuchos::RCP getM() const { return( _MOp ); }; + + //! Get a pointer to the preconditioner of the eigenproblem \f$Ax=\lambda Mx\f$. + Teuchos::RCP getPrec() const { return( _Prec ); }; + + //! Get a pointer to the initial vector + Teuchos::RCP getInitVec() const { return( _InitVec ); }; + + //! Get a pointer to the auxiliary vector + Teuchos::RCP getAuxVecs() const { return( _AuxVecs ); }; + + //! Get the number of eigenvalues (NEV) that are required by this eigenproblem. + int getNEV() const { return( _nev ); } + + //! Get the symmetry information for this eigenproblem. + bool isHermitian() const { return( _isSym ); } + + //! If the problem has been set, this method will return true. + bool isProblemSet() const { return( _isSet ); } + + /*! \brief Get the solution to the eigenproblem. + * + * There is no computation associated with this method. It only provides a + * mechanism for associating an Eigensolution with a Eigenproblem. + */ + const Eigensolution & getSolution() const { return(_sol); } + + //@} + + protected: + + //! Reference-counted pointer for \c A of the eigenproblem \f$Ax=\lambda Mx\f$ + Teuchos::RCP _AOp; + + //! Reference-counted pointer for \c M of the eigenproblem \f$Ax=\lambda Mx\f$ + Teuchos::RCP _MOp; + + //! Reference-counted pointer for the operator of the eigenproblem \f$Ax=\lambda Mx\f$ + Teuchos::RCP _Op; + + //! Reference-counted pointer for the preconditioner of the eigenproblem \f$Ax=\lambda Mx\f$ + Teuchos::RCP _Prec; + + //! Reference-counted pointer for the initial vector of the eigenproblem \f$Ax=\lambda Mx\f$ + Teuchos::RCP _InitVec; + + //! Reference-counted pointer for the auxiliary vector of the eigenproblem \f$Ax=\lambda Mx\f$ + Teuchos::RCP _AuxVecs; + + //! Number of eigenvalues requested + int _nev; + + //! Symmetry of the eigenvalue problem + /*! \note A generalized eigenvalue problem \f$Ax= \lambda Mx\f$ is considered symmetric + if the operator \c M is positive (semi) definite. + */ + bool _isSym; + + //! Sanity Check Flag + bool _isSet; + + //! Type-definition for the MultiVecTraits class corresponding to the \c MV type + typedef MultiVecTraits MVT; + //! Type-definition for the OperatorTraits class corresponding to the \c OP type + typedef OperatorTraits OPT; + + //! Solution to problem + Eigensolution _sol; + }; + + + //============================================================================= + // Implementations (Constructors / Destructors) + //============================================================================= + template + BasicEigenproblem::BasicEigenproblem() : + _nev(0), + _isSym(false), + _isSet(false) + { + } + + + //============================================================================= + template + BasicEigenproblem::BasicEigenproblem( const Teuchos::RCP& Op, const Teuchos::RCP& InitVec ) : + _Op(Op), + _InitVec(InitVec), + _nev(0), + _isSym(false), + _isSet(false) + { + } + + + //============================================================================= + template + BasicEigenproblem::BasicEigenproblem( const Teuchos::RCP& Op, const Teuchos::RCP& M, + const Teuchos::RCP& InitVec ) : + _MOp(M), + _Op(Op), + _InitVec(InitVec), + _nev(0), + _isSym(false), + _isSet(false) + { + } + + + //============================================================================= + template + BasicEigenproblem::BasicEigenproblem( const BasicEigenproblem& Problem ) : + _AOp(Problem._AOp), + _MOp(Problem._MOp), + _Op(Problem._Op), + _Prec(Problem._Prec), + _InitVec(Problem._InitVec), + _nev(Problem._nev), + _isSym(Problem._isSym), + _isSet(Problem._isSet), + _sol(Problem._sol) + { + } + + + //============================================================================= + // SetProblem (sanity check method) + //============================================================================= + template + bool BasicEigenproblem::setProblem() + { + //---------------------------------------------------------------- + // Sanity Checks + //---------------------------------------------------------------- + // If there is no operator, then we can't proceed. + if ( !_AOp.get() && !_Op.get() ) { return false; } + + // If there is no initial vector, then we don't have anything to clone workspace from. + if ( !_InitVec.get() ) { return false; } + + // If we don't need any eigenvalues, we don't need to continue. + if (_nev == 0) { return false; } + + // If there is an A, but no operator, we can set them equal. + if (_AOp.get() && !_Op.get()) { _Op = _AOp; } + + // Clear the storage from any previous call to setSolution() + Eigensolution emptysol; + _sol = emptysol; + + // mark the problem as set and return no-error + _isSet=true; + return true; + } + +} // end Anasazi namespace +#endif + +// end AnasaziBasicEigenproblem.hpp diff --git a/fastlib/trilinos/include/AnasaziBasicOrthoManager.hpp b/fastlib/trilinos/include/AnasaziBasicOrthoManager.hpp new file mode 100644 index 0000000000..99a19421d2 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziBasicOrthoManager.hpp @@ -0,0 +1,893 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +/*! \file AnasaziBasicOrthoManager.hpp + \brief Basic implementation of the Anasazi::OrthoManager class +*/ + +#ifndef ANASAZI_BASIC_ORTHOMANAGER_HPP +#define ANASAZI_BASIC_ORTHOMANAGER_HPP + +/*! \class Anasazi::BasicOrthoManager + \brief An implementation of the Anasazi::MatOrthoManager that performs orthogonalization + using (potentially) multiple steps of classical Gram-Schmidt. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +// #define ANASAZI_BASICORTHO_DEBUG + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "AnasaziMatOrthoManager.hpp" +#include "Teuchos_TimeMonitor.hpp" + +namespace Anasazi { + + template + class BasicOrthoManager : public MatOrthoManager { + + private: + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits SCT; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + + public: + + //! @name Constructor/Destructor + //@{ + //! Constructor specifying re-orthogonalization tolerance. + BasicOrthoManager( Teuchos::RCP Op = Teuchos::null, typename Teuchos::ScalarTraits::magnitudeType kappa = 1.5625 ); + + + //! Destructor + ~BasicOrthoManager() {} + //@} + + + //! @name Accessor routines + //@{ + + //! Set parameter for re-orthogonalization threshold. + void setKappa( typename Teuchos::ScalarTraits::magnitudeType kappa ) { kappa_ = kappa; } + + //! Return parameter for re-orthogonalization threshold. + typename Teuchos::ScalarTraits::magnitudeType getKappa() const { return kappa_; } + + //@} + + + //! @name Methods implementing Anasazi::MatOrthoManager + //@{ + + + /*! \brief Given a list of mutually orthogonal and internally orthonormal bases \c Q, this method + * projects a multivector \c X onto the space orthogonal to the individual Q[i], + * optionally returning the coefficients of \c X for the individual Q[i]. All of this is done with respect + * to the inner product innerProd(). + * + * After calling this routine, \c X will be orthogonal to each of the Q[i]. + * + @param X [in/out] The multivector to be modified.
+ On output, the columns of \c X will be orthogonal to each Q[i], satisfying + \f[ + X_{out} = X_{in} - \sum_i Q[i] \langle Q[i], X_{in} \rangle + \f] + + @param MX [in/out] The image of \c X under the inner product operator \c Op. + If \f$ MX != 0\f$: On input, this is expected to be consistent with \c Op \cdot X. On output, this is updated consistent with updates to \c X. + If \f$ MX == 0\f$ or \f$ Op == 0\f$: \c MX is not referenced. + + @param C [out] The coefficients of \c X in the bases Q[i]. If C[i] is a non-null pointer + and C[i] matches the dimensions of \c X and Q[i], then the coefficients computed during the orthogonalization + routine will be stored in the matrix C[i], similar to calling + \code + innerProd( Q[i], X, C[i] ); + \endcode + If C[i] points to a Teuchos::SerialDenseMatrix with size + inconsistent with \c X and \c Q[i], then a std::invalid_argument + exception will be thrown. Otherwise, if C.size() < i or + C[i] is a null pointer, the caller will not have access to the + computed coefficients. + + @param Q [in] A list of multivector bases specifying the subspaces to be orthogonalized against, satisfying + \f[ + \langle Q[i], Q[j] \rangle = I \quad\textrm{if}\quad i=j + \f] + and + \f[ + \langle Q[i], Q[j] \rangle = 0 \quad\textrm{if}\quad i \neq j\ . + \f] + */ + void projectMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const; + + + /*! \brief This method takes a multivector \c X and attempts to compute an orthonormal basis for \f$colspan(X)\f$, with respect to innerProd(). + * + * The method uses classical Gram-Schmidt with selective reorthogonalization. As a result, the coefficient matrix \c B is upper triangular. + * + * This routine returns an integer \c rank stating the rank of the computed basis. If \c X does not have full rank and the normalize() routine does + * not attempt to augment the subspace, then \c rank may be smaller than the number of columns in \c X. In this case, only the first \c rank columns of + * output \c X and first \c rank rows of \c B will be valid. + * + * The method attempts to find a basis with dimension equal to the number of columns in \c X. It does this by augmenting linearly dependent + * vectors in \c X with random directions. A finite number of these attempts will be made; therefore, it is possible that the dimension of the + * computed basis is less than the number of vectors in \c X. + * + @param X [in/out] The multivector to be modified.
+ On output, the first \c rank columns of \c X satisfy + \f[ + \langle X[i], X[j] \rangle = \delta_{ij}\ . + \f] + Also, + \f[ + X_{in}(1:m,1:n) = X_{out}(1:m,1:rank) B(1:rank,1:n) + \f] + where \c m is the number of rows in \c X and \c n is the number of columns in \c X. + + @param MX [in/out] The image of \c X under the inner product operator \c Op. + If \f$ MX != 0\f$: On input, this is expected to be consistent with \c Op \cdot X. On output, this is updated consistent with updates to \c X. + If \f$ MX == 0\f$ or \f$ Op == 0\f$: \c MX is not referenced. + + @param B [out] The coefficients of the original \c X with respect to the computed basis. If \c B is a non-null pointer and \c B matches the dimensions of \c B, then the + coefficients computed during the orthogonalization routine will be stored in \c B, similar to calling + \code + innerProd( Xout, Xin, B ); + \endcode + If \c B points to a Teuchos::SerialDenseMatrix with size inconsistent with \c X, then a std::invalid_argument exception will be thrown. Otherwise, if \c B is null, the caller will not have + access to the computed coefficients. This matrix is not necessarily triangular (as in a QR factorization); see the documentation of specific orthogonalization managers.
+ The first rows in \c B corresponding to the valid columns in \c X will be upper triangular. + + @return Rank of the basis computed by this method, less than or equal to the number of columns in \c X. This specifies how many columns in the returned \c X and rows in the returned \c B are valid. + */ + int normalizeMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::RCP > B = Teuchos::tuple(Teuchos::null) ) const; + + + /*! \brief Given a set of bases Q[i] and a multivector \c X, this method computes an orthonormal basis for \f$colspan(X) - \sum_i colspan(Q[i])\f$. + * + * This routine returns an integer \c rank stating the rank of the computed basis. If the subspace \f$colspan(X) - \sum_i colspan(Q[i])\f$ does not + * have dimension as large as the number of columns of \c X and the orthogonalization manager doe not attempt to augment the subspace, then \c rank + * may be smaller than the number of columns of \c X. In this case, only the first \c rank columns of output \c X and first \c rank rows of \c B will + * be valid. + * + * The method attempts to find a basis with dimension the same as the number of columns in \c X. It does this by augmenting linearly dependent + * vectors with random directions. A finite number of these attempts will be made; therefore, it is possible that the dimension of the + * computed basis is less than the number of vectors in \c X. + * + @param X [in/out] The multivector to be modified.
+ On output, the first \c rank columns of \c X satisfy + \f[ + \langle X[i], X[j] \rangle = \delta_{ij} \quad \textrm{and} \quad \langle X, Q[i] \rangle = 0\ . + \f] + Also, + \f[ + X_{in}(1:m,1:n) = X_{out}(1:m,1:rank) B(1:rank,1:n) + \sum_i Q[i] C[i] + \f] + where \c m is the number of rows in \c X and \c n is the number of columns in \c X. + + @param MX [in/out] The image of \c X under the inner product operator \c Op. + If \f$ MX != 0\f$: On input, this is expected to be consistent with \c Op \cdot X. On output, this is updated consistent with updates to \c X. + If \f$ MX == 0\f$ or \f$ Op == 0\f$: \c MX is not referenced. + + @param C [out] The coefficients of \c X in the Q[i]. If C[i] is a non-null pointer + and C[i] matches the dimensions of \c X and Q[i], then the coefficients computed during the orthogonalization + routine will be stored in the matrix C[i], similar to calling + \code + innerProd( Q[i], X, C[i] ); + \endcode + If C[i] points to a Teuchos::SerialDenseMatrix with size + inconsistent with \c X and \c Q[i], then a std::invalid_argument + exception will be thrown. Otherwise, if C.size() < i or + C[i] is a null pointer, the caller will not have access to the + computed coefficients. + + @param B [out] The coefficients of the original \c X with respect to the computed basis. If \c B is a non-null pointer and \c B matches the dimensions of \c B, then the + coefficients computed during the orthogonalization routine will be stored in \c B, similar to calling + \code + innerProd( Xout, Xin, B ); + \endcode + If \c B points to a Teuchos::SerialDenseMatrix with size inconsistent with \c X, then a std::invalid_argument exception will be thrown. Otherwise, if \c B is null, the caller will not have + access to the computed coefficients. This matrix is not necessarily triangular (as in a QR factorization); see the documentation of specific orthogonalization managers.
+ The first rows in \c B corresponding to the valid columns in \c X will be upper triangular. + + @param Q [in] A list of multivector bases specifying the subspaces to be orthogonalized against, satisfying + \f[ + \langle Q[i], Q[j] \rangle = I \quad\textrm{if}\quad i=j + \f] + and + \f[ + \langle Q[i], Q[j] \rangle = 0 \quad\textrm{if}\quad i \neq j\ . + \f] + + @return Rank of the basis computed by this method, less than or equal to the number of columns in \c X. This specifies how many columns in the returned \c X and rows in the returned \c B are valid. + + */ + int projectAndNormalizeMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::RCP > B = Teuchos::null, + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const; + + //@} + + //! @name Error methods + //@{ + + /*! \brief This method computes the error in orthonormality of a multivector, measured + * as the Frobenius norm of the difference innerProd(X,Y) - I. + * The method has the option of exploiting a caller-provided \c MX. + */ + typename Teuchos::ScalarTraits::magnitudeType + orthonormErrorMat(const MV &X, Teuchos::RCP MX = Teuchos::null) const; + + /*! \brief This method computes the error in orthogonality of two multivectors, measured + * as the Frobenius norm of innerProd(X,Y). + * The method has the option of exploiting a caller-provided \c MX. + */ + typename Teuchos::ScalarTraits::magnitudeType + orthogErrorMat(const MV &X1, Teuchos::RCP MX1, const MV &X2) const; + + //@} + + private: + + //! Parameter for re-orthogonalization. + MagnitudeType kappa_; + + // ! Routine to find an orthonormal basis for the + int findBasis(MV &X, Teuchos::RCP MX, + Teuchos::RCP > C, + bool completeBasis, int howMany = -1 ) const; + + // + // Internal timers + // + Teuchos::RCP timerReortho_; + + }; + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + template + BasicOrthoManager::BasicOrthoManager( Teuchos::RCP Op, + typename Teuchos::ScalarTraits::magnitudeType kappa ) : + MatOrthoManager(Op), + kappa_(kappa), + timerReortho_(Teuchos::TimeMonitor::getNewTimer("BasicOrthoManager::Re-orthogonalization")) + {} + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Compute the distance from orthonormality + template + typename Teuchos::ScalarTraits::magnitudeType + BasicOrthoManager::orthonormErrorMat(const MV &X, Teuchos::RCP MX) const { + const ScalarType ONE = SCT::one(); + int rank = MVT::GetNumberVecs(X); + Teuchos::SerialDenseMatrix xTx(rank,rank); + innerProdMat(X,X,MX,xTx); + for (int i=0; i + typename Teuchos::ScalarTraits::magnitudeType + BasicOrthoManager::orthogErrorMat(const MV &X1, Teuchos::RCP MX1, const MV &X2) const { + int r1 = MVT::GetNumberVecs(X1); + int r2 = MVT::GetNumberVecs(X2); + Teuchos::SerialDenseMatrix xTx(r2,r1); + innerProdMat(X2,X1,MX1,xTx); + return xTx.normFrobenius(); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Find an Op-orthonormal basis for span(X) - span(W) + template + int BasicOrthoManager::projectAndNormalizeMat( + MV &X, Teuchos::RCP MX, + Teuchos::Array > > C, + Teuchos::RCP > B, + Teuchos::Array > Q ) const { + + int nq = Q.length(); + int xc = MVT::GetNumberVecs( X ); + int xr = MVT::GetVecLength( X ); + int rank; + + /* if the user doesn't want to store the coefficients, + * allocate some local memory for them + */ + if ( B == Teuchos::null ) { + B = Teuchos::rcp( new Teuchos::SerialDenseMatrix(xc,xc) ); + } + + /****** DO NO MODIFY *MX IF _hasOp == false ******/ + if (this->_hasOp) { + if (MX == Teuchos::null) { + // we need to allocate space for MX + MX = MVT::Clone(X,MVT::GetNumberVecs(X)); + OPT::Apply(*(this->_Op),X,*MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + } + else { + // Op == I --> MX = X (ignore it if the user passed it in) + MX = Teuchos::rcp( &X, false ); + } + + int mxc = MVT::GetNumberVecs( *MX ); + int mxr = MVT::GetVecLength( *MX ); + + // short-circuit + TEST_FOR_EXCEPTION( xc == 0 || xr == 0, std::invalid_argument, "Anasazi::BasicOrthoManager::projectAndNormalizeMat(): X must be non-empty" ); + + int numbas = 0; + for (int i=0; inumRows() != xc || B->numCols() != xc, std::invalid_argument, + "Anasazi::BasicOrthoManager::projectAndNormalizeMat(): Size of X must be consistant with size of B" ); + // check size of X and MX + TEST_FOR_EXCEPTION( xc<0 || xr<0 || mxc<0 || mxr<0, std::invalid_argument, + "Anasazi::BasicOrthoManager::projectAndNormalizeMat(): MVT returned negative dimensions for X,MX" ); + // check size of X w.r.t. MX + TEST_FOR_EXCEPTION( xc!=mxc || xr!=mxr, std::invalid_argument, + "Anasazi::BasicOrthoManager::projectAndNormalizeMat(): Size of X must be consistant with size of MX" ); + // check feasibility + TEST_FOR_EXCEPTION( numbas+xc > xr, std::invalid_argument, + "Anasazi::BasicOrthoManager::projectAndNormalizeMat(): Orthogonality constraints not feasible" ); + + // orthogonalize all of X against Q + projectMat(X,MX,C,Q); + + + Teuchos::SerialDenseMatrix oldCoeff(xc,1); + + // start working + rank = 0; + int numTries = 10; // each vector in X gets 10 random chances to escape degeneracy + int oldrank = -1; + do { + int curxsize = xc - rank; + + // orthonormalize X, but quit if it is rank deficient + // we can't let findBasis generated random vectors to complete the basis, + // because it doesn't know about Q; we will do this ourselves below + rank = findBasis(X,MX,B,false,curxsize); + + if (rank < xc && numTries == 10) { + // we quit on this vector, and for the first time; + // save the coefficient information, because findBasis will overwrite it + for (int i=0; i curX, curMX; + std::vector ind(1); + ind[0] = rank; + curX = MVT::CloneView(X,ind); + MVT::MvRandom(*curX); + if (this->_hasOp) { + curMX = MVT::CloneView(*MX,ind); + OPT::Apply( *(this->_Op), *curX, *curMX ); + this->_OpCounter += MVT::GetNumberVecs(*curX); + } + + // orthogonalize against Q + // if !this->_hasOp, the curMX will be ignored. + // we don't care about these coefficients; in fact, we need to preserve the previous coeffs + projectMat(*curX,curMX,Teuchos::null,Q); + } + } while (1); + + // this should never raise an exception; but our post-conditions oblige us to check + TEST_FOR_EXCEPTION( rank > xc || rank < 0, std::logic_error, + "Anasazi::BasicOrthoManager::projectAndNormalizeMat(): Debug error in rank variable." ); + return rank; + } + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Find an Op-orthonormal basis for span(X), with rank numvectors(X) + template + int BasicOrthoManager::normalizeMat( + MV &X, Teuchos::RCP MX, + Teuchos::RCP > B ) const { + // call findBasis, with the instruction to try to generate a basis of rank numvecs(X) + return findBasis(X, MX, B, true ); + } + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + template + void BasicOrthoManager::projectMat( + MV &X, Teuchos::RCP MX, + Teuchos::Array > > C, + Teuchos::Array > Q) const { + // For the inner product defined by the operator Op or the identity (Op == 0) + // -> Orthogonalize X against each Q[i] + // Modify MX accordingly + // + // Note that when Op is 0, MX is not referenced + // + // Parameter variables + // + // X : Vectors to be transformed + // + // MX : Image of the block vector X by the mass matrix + // + // Q : Bases to orthogonalize against. These are assumed orthonormal, mutually and independently. + // + + ScalarType ONE = SCT::one(); + + int xc = MVT::GetNumberVecs( X ); + int xr = MVT::GetVecLength( X ); + int nq = Q.length(); + std::vector qcs(nq); + // short-circuit + if (nq == 0 || xc == 0 || xr == 0) { + return; + } + int qr = MVT::GetVecLength ( *Q[0] ); + // if we don't have enough C, expand it with null references + // if we have too many, resize to throw away the latter ones + // if we have exactly as many as we have Q, this call has no effect + C.resize(nq); + + + /****** DO NO MODIFY *MX IF _hasOp == false ******/ + if (this->_hasOp) { + if (MX == Teuchos::null) { + // we need to allocate space for MX + MX = MVT::Clone(X,MVT::GetNumberVecs(X)); + OPT::Apply(*(this->_Op),X,*MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + } + else { + // Op == I --> MX = X (ignore it if the user passed it in) + MX = Teuchos::rcp( &X, false ); + } + int mxc = MVT::GetNumberVecs( *MX ); + int mxr = MVT::GetVecLength( *MX ); + + // check size of X and Q w.r.t. common sense + TEST_FOR_EXCEPTION( xc<0 || xr<0 || mxc<0 || mxr<0, std::invalid_argument, + "Anasazi::BasicOrthoManager::projectMat(): MVT returned negative dimensions for X,MX" ); + // check size of X w.r.t. MX and Q + TEST_FOR_EXCEPTION( xc!=mxc || xr!=mxr || xr!=qr, std::invalid_argument, + "Anasazi::BasicOrthoManager::projectMat(): Size of X not consistant with MX,Q" ); + + // tally up size of all Q and check/allocate C + int baslen = 0; + for (int i=0; i(qcs[i],xc) ); + } + else { + TEST_FOR_EXCEPTION( C[i]->numRows() != qcs[i] || C[i]->numCols() != xc , std::invalid_argument, + "Anasazi::BasicOrthoManager::projectMat(): Size of Q not consistant with size of C" ); + } + } + + // Perform the Gram-Schmidt transformation for a block of vectors + + // Compute the initial Op-norms + std::vector oldDot( xc ); + MVT::MvDot( X, *MX, &oldDot ); + + Teuchos::Array > MQ(nq); + // Define the product Q^T * (Op*X) + for (int i=0; i_hasOp) { + if (xc <= qcs[i]) { + OPT::Apply( *(this->_Op), X, *MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + else { + // this will possibly be used again below; don't delete it + MQ[i] = MVT::Clone( *Q[i], qcs[i] ); + OPT::Apply( *(this->_Op), *Q[i], *MQ[i] ); + this->_OpCounter += MVT::GetNumberVecs(*Q[i]); + MVT::MvTimesMatAddMv( -ONE, *MQ[i], *C[i], ONE, *MX ); + } + } + } + + // Compute new Op-norms + std::vector newDot(xc); + MVT::MvDot( X, *MX, &newDot ); + + // determine (individually) whether to do another step of classical Gram-Schmidt + for (int j = 0; j < xc; ++j) { + + if ( SCT::magnitude(kappa_*newDot[j]) < SCT::magnitude(oldDot[j]) ) { + Teuchos::TimeMonitor lcltimer( *timerReortho_ ); + for (int i=0; i C2(*C[i]); + + // Apply another step of classical Gram-Schmidt + innerProdMat(*Q[i],X,MX,C2); + *C[i] += C2; + MVT::MvTimesMatAddMv( -ONE, *Q[i], C2, ONE, X ); + + // Update MX, with the least number of applications of Op as possible + if (this->_hasOp) { + if (MQ[i].get()) { + // MQ was allocated and computed above; use it + MVT::MvTimesMatAddMv( -ONE, *MQ[i], C2, ONE, *MX ); + } + else if (xc <= qcs[i]) { + // MQ was not allocated and computed above; it was cheaper to use X before and it still is + OPT::Apply( *(this->_Op), X, *MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + } + } + break; + } // if (kappa_*newDot[j] < oldDot[j]) + } // for (int j = 0; j < xc; ++j) + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Find an Op-orthonormal basis for span(X), with the option of extending the subspace so that + // the rank is numvectors(X) + template + int BasicOrthoManager::findBasis( + MV &X, Teuchos::RCP MX, + Teuchos::RCP > B, + bool completeBasis, int howMany ) const { + + using std::cout; + using std::endl; + + // For the inner product defined by the operator Op or the identity (Op == 0) + // -> Orthonormalize X + // Modify MX accordingly + // + // Note that when Op is 0, MX is not referenced + // + // Parameter variables + // + // X : Vectors to be orthonormalized + // + // MX : Image of the multivector X under the operator Op + // + // Op : Pointer to the operator for the inner product + // + // TODO: add reference + // kappa= Coefficient determining when to perform a second Gram-Schmidt step + // Default value = 1.5625 = (1.25)^2 (as suggested in Parlett's book) + // + + const ScalarType ONE = SCT::one(); + const MagnitudeType ZERO = SCT::magnitude(SCT::zero()); + const ScalarType EPS = SCT::eps(); + + int xc = MVT::GetNumberVecs( X ); + int xr = MVT::GetVecLength( X ); + + if (howMany == -1) { + howMany = xc; + } + + /******************************************************* + * If _hasOp == false, we will not reference MX below * + *******************************************************/ + + // if Op==null, MX == X (via pointer) + // Otherwise, either the user passed in MX or we will allocated and compute it + if (this->_hasOp) { + if (MX == Teuchos::null) { + // we need to allocate space for MX + MX = MVT::Clone(X,xc); + OPT::Apply(*(this->_Op),X,*MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + } + + /* if the user doesn't want to store the coefficients, + * allocate some local memory for them + */ + if ( B == Teuchos::null ) { + B = Teuchos::rcp( new Teuchos::SerialDenseMatrix(xc,xc) ); + } + + int mxc = (this->_hasOp) ? MVT::GetNumberVecs( *MX ) : xc; + int mxr = (this->_hasOp) ? MVT::GetVecLength( *MX ) : xr; + + // check size of C, B + TEST_FOR_EXCEPTION( xc == 0 || xr == 0, std::invalid_argument, + "Anasazi::BasicOrthoManager::findBasis(): X must be non-empty" ); + TEST_FOR_EXCEPTION( B->numRows() != xc || B->numCols() != xc, std::invalid_argument, + "Anasazi::BasicOrthoManager::findBasis(): Size of X not consistant with size of B" ); + TEST_FOR_EXCEPTION( xc != mxc || xr != mxr, std::invalid_argument, + "Anasazi::BasicOrthoManager::findBasis(): Size of X not consistant with size of MX" ); + TEST_FOR_EXCEPTION( xc > xr, std::invalid_argument, + "Anasazi::BasicOrthoManager::findBasis(): Size of X not feasible for normalization" ); + TEST_FOR_EXCEPTION( howMany < 0 || howMany > xc, std::invalid_argument, + "Anasazi::BasicOrthoManager::findBasis(): Invalid howMany parameter" ); + + /* xstart is which column we are starting the process with, based on howMany + * columns before xstart are assumed to be Op-orthonormal already + */ + int xstart = xc - howMany; + + for (int j = xstart; j < xc; j++) { + + // numX represents the number of currently orthonormal columns of X + int numX = j; + // j represents the index of the current column of X + // these are different interpretations of the same value + + // + // set the lower triangular part of R to zero + for (int i=j+1; i index(1); + index[0] = j; + Teuchos::RCP Xj = MVT::CloneView( X, index ); + Teuchos::RCP MXj; + if ((this->_hasOp)) { + // MXj is a view of the current vector in MX + MXj = MVT::CloneView( *MX, index ); + } + else { + // MXj is a pointer to Xj, and MUST NOT be modified + MXj = Xj; + } + + // Get a view of the previous vectors. + std::vector prev_idx( numX ); + Teuchos::RCP prevX, prevMX; + + if (numX > 0) { + for (int i=0; i_hasOp) { + prevMX = MVT::CloneView( *MX, prev_idx ); + } + } + + bool rankDef = true; + /* numTrials>0 will denote that the current vector was randomized for the purpose + * of finding a basis vector, and that the coefficients of that vector should + * not be stored in B + */ + for (int numTrials = 0; numTrials < 10; numTrials++) { + + // Make storage for these Gram-Schmidt iterations. + Teuchos::SerialDenseMatrix product(numX, 1); + std::vector oldDot( 1 ), newDot( 1 ); + + // + // Save old MXj vector and compute Op-norm + // + Teuchos::RCP oldMXj = MVT::CloneCopy( *MXj ); + MVT::MvDot( *Xj, *MXj, &oldDot ); + // Xj^H Op Xj should be real and positive, by the Hermitian positive definiteness of Op + TEST_FOR_EXCEPTION( SCT::real(oldDot[0]) < ZERO, OrthoError, + "Anasazi::BasicOrthoManager::findBasis(): Negative definiteness discovered in inner product" ); + + if (numX > 0) { + // Apply the first step of Gram-Schmidt + + // product <- prevX^T MXj + innerProdMat(*prevX,*Xj,MXj,product); + + // Xj <- Xj - prevX prevX^T MXj + // = Xj - prevX product + MVT::MvTimesMatAddMv( -ONE, *prevX, product, ONE, *Xj ); + + // Update MXj + if (this->_hasOp) { + // MXj <- Op*Xj_new + // = Op*(Xj_old - prevX prevX^T MXj) + // = MXj - prevMX product + MVT::MvTimesMatAddMv( -ONE, *prevMX, product, ONE, *MXj ); + } + + // Compute new Op-norm + MVT::MvDot( *Xj, *MXj, &newDot ); + + // Check if a correction is needed. + if ( SCT::magnitude(kappa_*newDot[0]) < SCT::magnitude(oldDot[0]) ) { + // Apply the second step of Gram-Schmidt + // This is the same as above + Teuchos::SerialDenseMatrix P2(numX,1); + + innerProdMat(*prevX,*Xj,MXj,P2); + product += P2; + MVT::MvTimesMatAddMv( -ONE, *prevX, P2, ONE, *Xj ); + if ((this->_hasOp)) { + MVT::MvTimesMatAddMv( -ONE, *prevMX, P2, ONE, *MXj ); + } + } // if (kappa_*newDot[0] < oldDot[0]) + + } // if (numX > 0) + + // Compute Op-norm with old MXj + MVT::MvDot( *Xj, *oldMXj, &newDot ); + + // save the coefficients, if we are working on the original vector and not a randomly generated one + if (numTrials == 0) { + for (int i=0; i SCT::magnitude(oldDot[0]*EPS*EPS) && SCT::real(newDot[0]) > ZERO ) { +#ifdef ANASAZI_BASICORTHO_DEBUG + cout << " ACCEPTED" << endl; +#endif + // Normalize Xj. + // Xj <- Xj / sqrt(newDot) + ScalarType diag = SCT::squareroot(SCT::magnitude(newDot[0])); + + MVT::MvAddMv( ONE/diag, *Xj, ZERO, *Xj, *Xj ); + if (this->_hasOp) { + // Update MXj. + MVT::MvAddMv( ONE/diag, *MXj, ZERO, *MXj, *MXj ); + } + + // save it, if it corresponds to the original vector and not a randomly generated one + if (numTrials == 0) { + (*B)(j,j) = diag; + } + + // We are not rank deficient in this vector. Move on to the next vector in X. + rankDef = false; + break; + } + else { +#ifdef ANASAZI_BASICORTHO_DEBUG + cout << " REJECTED" << endl; +#endif + // There was nothing left in Xj after orthogonalizing against previous columns in X. + // X is rank deficient. + // reflect this in the coefficients + (*B)(j,j) = ZERO; + + if (completeBasis) { + // Fill it with random information and keep going. +#ifdef ANASAZI_BASICORTHO_DEBUG + cout << "Random for column " << j << endl; +#endif + MVT::MvRandom( *Xj ); + if (this->_hasOp) { + OPT::Apply( *(this->_Op), *Xj, *MXj ); + this->_OpCounter += MVT::GetNumberVecs(*Xj); + } + } + else { + rankDef = true; + break; + } + + } // if (norm > oldDot*EPS*EPS) + + } // for (numTrials = 0; numTrials < 10; ++numTrials) + + // if rankDef == true, then quit and notify user of rank obtained + if (rankDef == true) { + MVT::MvInit( *Xj, ZERO ); + if (this->_hasOp) { + MVT::MvInit( *MXj, ZERO ); + } + TEST_FOR_EXCEPTION( completeBasis, OrthoError, + "Anasazi::BasicOrthoManager::findBasis(): Unable to complete basis" ); + return j; + } + + } // for (j = 0; j < xc; ++j) + + return xc; + } + +} // namespace Anasazi + +#endif // ANASAZI_BASIC_ORTHOMANAGER_HPP + diff --git a/fastlib/trilinos/include/AnasaziBasicOutputManager.hpp b/fastlib/trilinos/include/AnasaziBasicOutputManager.hpp new file mode 100644 index 0000000000..523fd6cec2 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziBasicOutputManager.hpp @@ -0,0 +1,170 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_BASIC_OUTPUT_MANAGER_HPP +#define ANASAZI_BASIC_OUTPUT_MANAGER_HPP + +/*! \file AnasaziBasicOutputManager.hpp + \brief Basic output manager for sending information of select verbosity levels to the appropriate output stream +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziOutputManager.hpp" +#include "Teuchos_oblackholestream.hpp" + +#ifdef HAVE_MPI +#include +#endif + +/*! \class Anasazi::BasicOutputManager + + \brief Anasazi's basic output manager for sending information of select verbosity levels + to the appropriate output stream. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +namespace Anasazi { + + using std::ostream; + + template + class BasicOutputManager : public OutputManager { + + public: + + //! @name Constructors/Destructor + //@{ + + //! Default constructor + BasicOutputManager( int vb = Anasazi::Errors, Teuchos::RCP os = Teuchos::rcp(&std::cout,false) ); + + //! Destructor. + virtual ~BasicOutputManager() {}; + //@} + + //! @name Set/Get methods + //@{ + + //! Set the output stream for this manager. + void setOStream( Teuchos::RCP os ); + + //! Get the output stream for this manager. + Teuchos::RCP getOStream(); + + //@} + + //! @name Output methods + //@{ + + //! Find out whether we need to print out information for this message type. + /*! This method is used by the solver to determine whether computations are + necessary for this message type. + */ + bool isVerbosity( MsgType type ) const; + + //! Send some output to this output stream. + void print( MsgType type, const std::string output ); + + //! Return a stream for outputting to. + ostream &stream( MsgType type ); + + //@} + + private: + + //! @name Undefined methods + //@{ + + //! Copy constructor. + BasicOutputManager( const OutputManager& OM ); + + //! Assignment operator. + BasicOutputManager& operator=( const OutputManager& OM ); + + //@} + + Teuchos::RCP myOS_; + Teuchos::oblackholestream myBHS_; + bool iPrint_; + }; + + template + BasicOutputManager::BasicOutputManager(int vb, Teuchos::RCP os) + : OutputManager(vb), myOS_(os) { + int MyPID; +#ifdef HAVE_MPI + // Initialize MPI + int mpiStarted = 0; + MPI_Initialized(&mpiStarted); + if (mpiStarted) MPI_Comm_rank(MPI_COMM_WORLD, &MyPID); + else MyPID=0; +#else + MyPID = 0; +#endif + iPrint_ = (MyPID == 0); + } + + template + void BasicOutputManager::setOStream( Teuchos::RCP os ) { + myOS_ = os; + } + + template + Teuchos::RCP BasicOutputManager::getOStream() { + return myOS_; + } + + template + bool BasicOutputManager::isVerbosity( MsgType type ) const { + if ( (type & this->vb_) == type ) { + return true; + } + return false; + } + + template + void BasicOutputManager::print( MsgType type, const std::string output ) { + if ( (type & this->vb_) == type && iPrint_ ) { + *myOS_ << output; + } + } + + template + ostream & BasicOutputManager::stream( MsgType type ) { + if ( (type & this->vb_) == type && iPrint_ ) { + return *myOS_; + } + return myBHS_; + } + +} // end Anasazi namespace + +#endif + +// end of file AnasaziOutputManager.hpp diff --git a/fastlib/trilinos/include/AnasaziBasicSort.hpp b/fastlib/trilinos/include/AnasaziBasicSort.hpp new file mode 100644 index 0000000000..45abb0683f --- /dev/null +++ b/fastlib/trilinos/include/AnasaziBasicSort.hpp @@ -0,0 +1,465 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziBasicSort.hpp + \brief Basic implementation of the Anasazi::SortManager class +*/ + +#ifndef ANASAZI_BASIC_SORT_HPP +#define ANASAZI_BASIC_SORT_HPP + +/*! \class Anasazi::BasicSort + \brief An implementation of the Anasazi::SortManager that performs a collection + of common sorting techniques. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziSortManager.hpp" +#include "Teuchos_LAPACK.hpp" +#include "Teuchos_ScalarTraits.hpp" + +namespace Anasazi { + + template + class BasicSort : public SortManager { + + public: + + //! Constructor + /** + @param which [in] The eigenvalues of interest for this eigenproblem. +
    +
  • "LM" - Largest Magnitude [ default ] +
  • "SM" - Smallest Magnitude +
  • "LR" - Largest Real +
  • "SR" - Smallest Real +
  • "LI" - Largest Imaginary +
  • "SI" - Smallest Imaginary +
+ */ + BasicSort( const std::string which = "LM" ) { + setSortType(which); + } + + //! Destructor + virtual ~BasicSort() {}; + + //! Set sort type + /** + @param which [in] The eigenvalues of interest for this eigenproblem. +
    +
  • "LM" - Largest Magnitude [ default ] +
  • "SM" - Smallest Magnitude +
  • "LR" - Largest Real +
  • "SR" - Smallest Real +
  • "LI" - Largest Imaginary +
  • "SI" - Smallest Imaginary +
+ */ + void setSortType( const std::string which ) { + which_ = which; + TEST_FOR_EXCEPTION(which_.compare("LM") && which_.compare("SM") && + which_.compare("LR") && which_.compare("SR") && + which_.compare("LI") && which_.compare("SI"), std::invalid_argument, + "Anasazi::BasicSort::sort(): sorting order is not valid"); + }; + + //! Sort the vector of eigenvalues, optionally returning the permutation vector. + /** + @param solver [in] Eigensolver that is calling the sorting routine + + @param n [in] Number of values in evals to be sorted. + + @param evals [in/out] Vector of length n containing the eigenvalues to be sorted + + @param perm [out] Vector of length n to store the permutation index (optional) + */ + void sort(Eigensolver* solver, const int n, std::vector::magnitudeType> &evals, std::vector *perm = 0) const; + + /*! \brief Sort the vectors of eigenpairs, optionally returning the permutation vector. + + This routine takes two vectors, one for each part of a complex + eigenvalue. This is helpful for solving real, non-symmetric eigenvalue + problems. + + @param solver [in] Eigensolver that is calling the sorting routine + + @param n [in] Number of values in r_evals,i_evals to be sorted. + + @param r_evals [in/out] Vector of length n containing the real part of the eigenvalues to be sorted + + @param i_evals [in/out] Vector of length n containing the imaginary part of the eigenvalues to be sorted + + @param perm [out] Vector of length n to store the permutation index (optional) + */ + void sort(Eigensolver* solver, + const int n, + std::vector::magnitudeType> &r_evals, + std::vector::magnitudeType> &i_evals, + std::vector *perm = 0) const; + + protected: + + //! Sorting type + /*! \note Sorting choices: +
    +
  • "LM" - Largest Magnitude [ default ] +
  • "SM" - Smallest Magnitude +
  • "LR" - Largest Real +
  • "SR" - Smallest Real +
  • "LI" - Largest Imaginary +
  • "SI" - Smallest Imaginary +
+ */ + std::string which_; + + }; + + template + void BasicSort::sort(Eigensolver* solver, const int n, + std::vector::magnitudeType> &evals, + std::vector *perm) const + { + int i=0,j=0; + + TEST_FOR_EXCEPTION(evals.size() < (unsigned int) n, + std::invalid_argument, "Anasazi::BasicSort:sort(): eigenvalue vector size isn't consistent with n."); + if (perm) { + TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n, + std::invalid_argument, "Anasazi::BasicSort:sort(): permutation vector size isn't consistent with n."); + } + + // Temp integer for swapping the index of the permutation, used in all sorting types. + int tempord=0; + + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + // Temp variable for swapping the eigenvalue used in all sorting types. + MagnitudeType temp; + + Teuchos::LAPACK lapack; + + // + // Reset the permutation if it is required. + // + if (perm) { + for (i=0; i < n; i++) { + (*perm)[i] = i; + } + } + // + // These methods use an insertion sort method to circumvent recursive calls. + //--------------------------------------------------------------- + // Sort eigenvalues in increasing order of magnitude + //--------------------------------------------------------------- + if (!which_.compare("SM")) { + for (j=1; j < n; j++) { + temp = evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + MagnitudeType temp2 = MT::magnitude(evals[j]); + for (i=j-1; i >=0 && MT::magnitude(evals[i]) > temp2; i--) { + evals[i+1] = evals[i]; + if (perm) { + (*perm)[i+1]=(*perm)[i]; + } + } + evals[i+1] = temp; + if (perm) { + (*perm)[i+1] = tempord; + } + } + return; + } + //--------------------------------------------------------------- + // Sort eigenvalues in increasing order of real part + //--------------------------------------------------------------- + if (!which_.compare("SR")) { + for (j=1; j < n; j++) { + temp = evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + for (i=j-1; i >= 0 && evals[i] > temp; i--) { + evals[i+1]=evals[i]; + if (perm) { + (*perm)[i+1]=(*perm)[i]; + } + } + evals[i+1] = temp; + if (perm) { + (*perm)[i+1] = tempord; + } + } + return; + } + //--------------------------------------------------------------- + // Sort eigenvalues in increasing order of imaginary part + // NOTE: There is no implementation for this since this sorting + // method assumes only real eigenvalues. + //--------------------------------------------------------------- + TEST_FOR_EXCEPTION(!which_.compare("SI"), SortManagerError, + "Anasazi::BasicSort::sort() with one arg assumes real eigenvalues"); + //--------------------------------------------------------------- + // Sort eigenvalues in decreasing order of magnitude + //--------------------------------------------------------------- + if (!which_.compare("LM")) { + for (j=1; j < n; j++) { + temp = evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + MagnitudeType temp2 = MT::magnitude(evals[j]); + for (i=j-1; i >= 0 && MT::magnitude(evals[i]) < temp2; i--) { + evals[i+1]=evals[i]; + if (perm) { + (*perm)[i+1]=(*perm)[i]; + } + } + evals[i+1] = temp; + if (perm) { + (*perm)[i+1] = tempord; + } + } + return; + } + //--------------------------------------------------------------- + // Sort eigenvalues in decreasing order of real part + //--------------------------------------------------------------- + if (!which_.compare("LR")) { + for (j=1; j < n; j++) { + temp = evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + for (i=j-1; i >= 0 && evals[i] + void BasicSort::sort(Eigensolver* solver, + const int n, + std::vector::magnitudeType> &r_evals, + std::vector::magnitudeType> &i_evals, + std::vector *perm) const + { + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + TEST_FOR_EXCEPTION(r_evals.size() < (unsigned int) n || i_evals.size() < (unsigned int) n, + std::invalid_argument, "Anasazi::BasicSort:sort(): real and imaginary vector sizes aren't consistent with n."); + if (perm) { + TEST_FOR_EXCEPTION(perm->size() < (unsigned int) n, + std::invalid_argument, "Anasazi::BasicSort:sort(): permutation vector size isn't consistent with n."); + } + int i=0,j=0; + int tempord=0; + + MagnitudeType temp, tempr, tempi; + Teuchos::LAPACK lapack; + // + // Reset the index + // + if (perm) { + for (i=0; i < n; i++) { + (*perm)[i] = i; + } + } + // + // These methods use an insertion sort method to circumvent recursive calls. + //--------------------------------------------------------------- + // Sort eigenvalues in increasing order of magnitude + //--------------------------------------------------------------- + if (!which_.compare("SM")) { + for (j=1; j < n; j++) { + tempr = r_evals[j]; tempi = i_evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + temp=lapack.LAPY2(r_evals[j],i_evals[j]); + for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i]) > temp; i--) { + r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; + if (perm) { + (*perm)[i+1]=(*perm)[i]; + } + } + r_evals[i+1] = tempr; i_evals[i+1] = tempi; + if (perm) { + (*perm)[i+1] = tempord; + } + } + return; + } + //--------------------------------------------------------------- + // Sort eigenvalues in increasing order of real part + //--------------------------------------------------------------- + if (!which_.compare("SR")) { + for (j=1; j < n; j++) { + tempr = r_evals[j]; tempi = i_evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + for (i=j-1; i>=0 && r_evals[i]>tempr; i--) { + r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; + if (perm) { + (*perm)[i+1]=(*perm)[i]; + } + } + r_evals[i+1] = tempr; i_evals[i+1] = tempi; + if (perm) { + (*perm)[i+1] = tempord; + } + } + return; + } + //--------------------------------------------------------------- + // Sort eigenvalues in increasing order of imaginary part + //--------------------------------------------------------------- + if (!which_.compare("SI")) { + for (j=1; j < n; j++) { + tempr = r_evals[j]; tempi = i_evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + for (i=j-1; i>=0 && i_evals[i]>tempi; i--) { + r_evals[i+1]=r_evals[i]; i_evals[i+1]=i_evals[i]; + if (perm) { + (*perm)[i+1]=(*perm)[i]; + } + } + r_evals[i+1] = tempr; i_evals[i+1] = tempi; + if (perm) { + (*perm)[i+1] = tempord; + } + } + return; + } + //--------------------------------------------------------------- + // Sort eigenvalues in decreasing order of magnitude + //--------------------------------------------------------------- + if (!which_.compare("LM")) { + for (j=1; j < n; j++) { + tempr = r_evals[j]; tempi = i_evals[j]; + if (perm) { + tempord = (*perm)[j]; + } + temp=lapack.LAPY2(r_evals[j],i_evals[j]); + for (i=j-1; i>=0 && lapack.LAPY2(r_evals[i],i_evals[i])=0 && r_evals[i]=0 && i_evals[i]A Comparison of Eigensolvers for + Large-scale 3D Modal Analysis Using AMG-Preconditioned Iterative + Methods, P. Arbenz, U. L. Hetmaniuk, R. B. Lehoucq, R. S. + Tuminaro, Internat. J. for Numer. Methods Engrg., 64, pp. 204-236 + (2005) + + \ingroup anasazi_solver_framework + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, Heidi Thornquist +*/ + +namespace Anasazi { + + //! @name BlockDavidson Structures + //@{ + + /** \brief Structure to contain pointers to BlockDavidson state variables. + * + * This struct is utilized by BlockDavidson::initialize() and BlockDavidson::getState(). + */ + template + struct BlockDavidsonState { + /*! \brief The current dimension of the solver. + * + * This should always be equal to BlockDavdison::getCurSubspaceDim() + */ + int curDim; + /*! \brief The basis for the Krylov space. + * + * V has BlockDavidson::getMaxSubspaceDim() vectors, but only the first \c curDim are valid. + */ + Teuchos::RCP V; + //! The current eigenvectors. + Teuchos::RCP X; + //! The image of the current eigenvectors under K. + Teuchos::RCP KX; + //! The image of the current eigenvectors under M, or Teuchos::null if M was not specified. + Teuchos::RCP MX; + //! The current residual vectors + Teuchos::RCP R; + /*! \brief The current preconditioned residual vectors. + * + * H is a pointer into V, and is only useful when BlockDavidson::iterate() throw a BlockDavidsonOrthoFailure exception. + */ + Teuchos::RCP H; + //! The current Ritz values. This vector is a copy of the internal + Teuchos::RCP::magnitudeType> > T; + /*! \brief The current projected K matrix. + * + * KK is of order BlockDavidson::getMaxSubspaceDim(), but only the principal submatrix of order \c curDim is meaningful. It is Hermitian in memory. + * + */ + Teuchos::RCP > KK; + BlockDavidsonState() : curDim(0), V(Teuchos::null), + X(Teuchos::null), KX(Teuchos::null), MX(Teuchos::null), + R(Teuchos::null), H(Teuchos::null), + T(Teuchos::null), KK(Teuchos::null) {} + }; + + //@} + + //! @name BlockDavidson Exceptions + //@{ + + /** \brief BlockDavidsonInitFailure is thrown when the BlockDavidson solver is unable to + * generate an initial iterate in the BlockDavidson::initialize() routine. + * + * This exception is thrown from the BlockDavidson::initialize() method, which is + * called by the user or from the BlockDavidson::iterate() method if isInitialized() + * == \c false. + * + * In the case that this exception is thrown, + * BlockDavidson::isInitialized() will be \c false and the user will need to provide + * a new initial iterate to the solver. + * + */ + class BlockDavidsonInitFailure : public AnasaziError {public: + BlockDavidsonInitFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + /** \brief BlockDavidsonOrthoFailure is thrown when the orthogonalization manager is + * unable to orthogonalize the preconditioned residual against (a.k.a. \c H) + * the current basis (a.k.a. \c V). + * + * This exception is thrown from the BlockDavidson::iterate() method. + * + */ + class BlockDavidsonOrthoFailure : public AnasaziError {public: + BlockDavidsonOrthoFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + //@} + + + template + class BlockDavidson : public Eigensolver { + public: + //! @name Constructor/Destructor + //@{ + + /*! \brief %BlockDavidson constructor with eigenproblem, solver utilities, and parameter list of solver options. + * + * This constructor takes pointers required by the eigensolver, in addition + * to a parameter list of options for the eigensolver. These options include the following: + * - "Block Size" - an \c int specifying the block size used by the algorithm. This can also be specified using the setBlockSize() method. + * - "Num Blocks" - an \c int specifying the maximum number of blocks allocated for the solver basis. + */ + BlockDavidson( const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms + ); + + //! %Anasazi::BlockDavidson destructor. + virtual ~BlockDavidson(); + //@} + + + //! @name Solver methods + //@{ + + /*! \brief This method performs %BlockDavidson iterations until the status + * test indicates the need to stop or an error occurs (in which case, an + * appropriate exception is thrown). + * + * iterate() will first determine whether the solver is uninitialized; if + * not, it will call initialize(). After + * initialization, the solver performs block Davidson iterations until the + * status test evaluates as ::Passed, at which point the method returns to + * the caller. + * + * The block Davidson iteration proceeds as follows: + * -# The current residual (R) is preconditioned to form H + * -# H is orthogonalized against the auxiliary vectors and the previous basis vectors, and made orthonormal. + * -# The current basis is expanded with H and used to project the problem matrix. + * -# The projected eigenproblem is solved, and the desired eigenvectors and eigenvalues are selected. + * -# These are used to form the new eigenvector estimates (X). + * -# The new residual (R) is formed. + * + * The status test is queried at the beginning of the iteration. + * + * Possible exceptions thrown include std::invalid_argument or + * one of the BlockDavidson-specific exceptions. + */ + void iterate(); + + /*! \brief Initialize the solver to an iterate, optionally providing the + * current basis and projected problem matrix, the current Ritz vectors and values, + * and the current residual. + * + * The %BlockDavidson eigensolver contains a certain amount of state, + * including the current Krylov basis, the current eigenvectors, + * the current residual, etc. (see getState()) + * + * initialize() gives the user the opportunity to manually set these, + * although this must be done with caution, as the validity of the + * user input will not be checked. + * + * \post + *
  • isInitialized() == \c true (see post-conditions of isInitialize()) + * + * The user has the option of specifying any component of the state using + * initialize(). However, these arguments are assumed to match the + * post-conditions specified under isInitialized(). Any component of the + * state (i.e., KX) not given to initialize() will be generated. + * + * Note, for any pointer in \c newstate which directly points to the multivectors in + * the solver, the data is not copied. + */ + void initialize(BlockDavidsonState newstate); + + /*! \brief Initialize the solver with the initial vectors from the eigenproblem + * or random data. + */ + void initialize(); + + /*! \brief Indicates whether the solver has been initialized or not. + * + * \return bool indicating the state of the solver. + * \post + * If isInitialized() == \c true: + * - getCurSubspaceDim() > 0 and is a multiple of getBlockSize() + * - the first getCurSubspaceDim() vectors of V are orthogonal to auxiliary vectors and have orthonormal columns + * - the principal submatrix of order getCurSubspaceDim() of KK contains the project eigenproblem matrix + * - X contains the Ritz vectors with respect to the current Krylov basis + * - T contains the Ritz values with respect to the current Krylov basis + * - KX == Op*X + * - MX == M*X if M != Teuchos::null\n + * Otherwise, MX == Teuchos::null + * - R contains the residual vectors with respect to X + */ + bool isInitialized() const; + + /*! \brief Get access to the current state of the eigensolver. + * + * The data is only valid if isInitialized() == \c true. + * + * The data for the preconditioned residual is only meaningful in the + * scenario that the solver throws a ::BlockDavidsonRitzFailure exception + * during iterate(). + * + * \returns A BlockDavidsonState object containing const pointers to the current + * solver state. Note, these are direct pointers to the multivectors; they are not + * pointers to views of the multivectors. + */ + BlockDavidsonState getState() const; + + //@} + + + //! @name Status methods + //@{ + + //! \brief Get the current iteration count. + int getNumIters() const; + + //! \brief Reset the iteration count. + void resetNumIters(); + + /*! \brief Get access to the current Ritz vectors. + + \return A multivector with getBlockSize() vectors containing + the sorted Ritz vectors corresponding to the most significant Ritz values. + The i-th vector of the return corresponds to the i-th Ritz vector; there is no need to use + getRitzIndex(). + */ + Teuchos::RCP getRitzVectors(); + + /*! \brief Get the Ritz values for the previous iteration. + * + * \return A vector of length getCurSubspaceDim() containing the Ritz values from the + * previous projected eigensolve. + */ + std::vector > getRitzValues(); + + + /*! \brief Get the index used for extracting individual Ritz vectors from getRitzVectors(). + * + * Because BlockDavidson is a Hermitian solver, all Ritz values are real and all Ritz vectors can be represented in a + * single column of a multivector. Therefore, getRitzIndex() is not needed when using the output from getRitzVectors(). + * + * \return An \c int vector of size getCurSubspaceDim() composed of zeros. + */ + std::vector getRitzIndex(); + + + /*! \brief Get the current residual norms, computing the norms if they are not up-to-date with the current residual vectors. + * + * \return A vector of length getCurSubspaceDim() containing the norms of the + * residuals, with respect to the orthogonalization manager's norm() method. + */ + std::vector::magnitudeType> getResNorms(); + + + /*! \brief Get the current residual 2-norms, computing the norms if they are not up-to-date with the current residual vectors. + * + * \return A vector of length getCurSubspaceDim() containing the 2-norms of the + * current residuals. + */ + std::vector::magnitudeType> getRes2Norms(); + + + /*! \brief Get the 2-norms of the residuals. + * + * The Ritz residuals are not defined for the %LOBPCG iteration. Hence, this method returns the + * 2-norms of the direct residuals, and is equivalent to calling getRes2Norms(). + * + * \return A vector of length getBlockSize() containing the 2-norms of the direct residuals. + */ + std::vector::magnitudeType> getRitzRes2Norms(); + + /*! \brief Get the dimension of the search subspace used to generate the current eigenvectors and eigenvalues. + * + * \return An integer specifying the rank of the Krylov subspace currently in use by the eigensolver. If isInitialized() == \c false, + * the return is 0. Otherwise, it will be some strictly positive multiple of getBlockSize(). + */ + int getCurSubspaceDim() const; + + //! Get the maximum dimension allocated for the search subspace. For %BlockDavidson, this always returns numBlocks*blockSize. + int getMaxSubspaceDim() const; + + //@} + + + //! @name Accessor routines from Eigensolver + //@{ + + + //! Get a constant reference to the eigenvalue problem. + const Eigenproblem& getProblem() const; + + /*! \brief Set the blocksize. + * + * This method is required to support the interface provided by Eigensolver. However, the preferred method + * of setting the allocated size for the BlockDavidson eigensolver is setSize(). In fact, setBlockSize() + * simply calls setSize(), maintaining the current number of blocks. + * + * The block size determines the number of Ritz vectors and values that are computed on each iteration, thereby + * determining the increase in the Krylov subspace at each iteration. + */ + void setBlockSize(int blockSize); + + //! Get the blocksize used by the iterative solver. + int getBlockSize() const; + + /*! \brief Set the auxiliary vectors for the solver. + * + * Because the current basis V cannot be assumed + * orthogonal to the new auxiliary vectors, a call to setAuxVecs() will + * reset the solver to the uninitialized state. This happens only in the + * case where the new auxiliary vectors have a combined dimension of + * greater than zero. + * + * In order to preserve the current state, the user will need to extract + * it from the solver using getState(), orthogonalize it against the + * new auxiliary vectors, and reinitialize using initialize(). + */ + void setAuxVecs(const Teuchos::Array > &auxvecs); + + //! Get the auxiliary vectors for the solver. + Teuchos::Array > getAuxVecs() const; + + //@} + + //! @name BlockDavidson-specific accessor routines + //@{ + + /*! \brief Set the blocksize and number of blocks to be used by the + * iterative solver in solving this eigenproblem. + * + * Changing either the block size or the number of blocks will reset the + * solver to an uninitialized state. + * + * The requested block size must be strictly positive; the number of blocks must be + * greater than one. Invalid arguments will result in a std::invalid_argument exception. + */ + void setSize(int blockSize, int numBlocks); + + //@} + + //! @name Output methods + //@{ + + //! This method requests that the solver print out its current status to the given output stream. + void currentStatus(std::ostream &os); + + //@} + + private: + // + // Convenience typedefs + // + typedef SolverUtils Utils; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + typedef Teuchos::ScalarTraits SCT; + typedef typename SCT::magnitudeType MagnitudeType; + const MagnitudeType ONE; + const MagnitudeType ZERO; + const MagnitudeType NANVAL; + // + // Internal structs + // + struct CheckList { + bool checkV; + bool checkX, checkMX, checkKX; + bool checkH, checkMH, checkKH; + bool checkR, checkQ; + bool checkKK; + CheckList() : checkV(false), + checkX(false),checkMX(false),checkKX(false), + checkH(false),checkMH(false),checkKH(false), + checkR(false),checkQ(false),checkKK(false) {}; + }; + // + // Internal methods + // + std::string accuracyCheck(const CheckList &chk, const std::string &where) const; + // + // Classes inputed through constructor that define the eigenproblem to be solved. + // + const Teuchos::RCP > problem_; + const Teuchos::RCP > sm_; + const Teuchos::RCP > om_; + const Teuchos::RCP > tester_; + const Teuchos::RCP > orthman_; + // + // Information obtained from the eigenproblem + // + Teuchos::RCP Op_; + Teuchos::RCP MOp_; + Teuchos::RCP Prec_; + bool hasM_; + // + // Internal timers + // + Teuchos::RCP timerOp_, timerMOp_, timerPrec_, + timerSortEval_, timerDS_, + timerLocal_, timerCompRes_, + timerOrtho_, timerInit_; + // + // Counters + // + int count_ApplyOp_, count_ApplyM_, count_ApplyPrec_; + + // + // Algorithmic parameters. + // + // blockSize_ is the solver block size; it controls the number of eigenvectors that + // we compute, the number of residual vectors that we compute, and therefore the number + // of vectors added to the basis on each iteration. + int blockSize_; + // numBlocks_ is the size of the allocated space for the Krylov basis, in blocks. + int numBlocks_; + + // + // Current solver state + // + // initialized_ specifies that the basis vectors have been initialized and the iterate() routine + // is capable of running; _initialize is controlled by the initialize() member method + // For the implications of the state of initialized_, please see documentation for initialize() + bool initialized_; + // + // curDim_ reflects how much of the current basis is valid + // NOTE: 0 <= curDim_ <= blockSize_*numBlocks_ + // this also tells us how many of the values in theta_ are valid Ritz values + int curDim_; + // + // State Multivecs + // H_,KH_,MH_ will not own any storage + // H_ will occasionally point at the current block of vectors in the basis V_ + // MH_,KH_ will occasionally point at MX_,KX_ when they are used as temporary storage + Teuchos::RCP X_, KX_, MX_, R_, + H_, KH_, MH_, + V_; + // + // Projected matrices + // + Teuchos::RCP > KK_; + // + // auxiliary vectors + Teuchos::Array > auxVecs_; + int numAuxVecs_; + // + // Number of iterations that have been performed. + int iter_; + // + // Current eigenvalues, residual norms + std::vector theta_, Rnorms_, R2norms_; + // + // are the residual norms current with the residual? + bool Rnorms_current_, R2norms_current_; + + }; + + ////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////// + // + // Implementations + // + ////////////////////////////////////////////////////////////////////////////////////////////////// + ////////////////////////////////////////////////////////////////////////////////////////////////// + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + template + BlockDavidson::BlockDavidson( + const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms + ) : + ONE(Teuchos::ScalarTraits::one()), + ZERO(Teuchos::ScalarTraits::zero()), + NANVAL(Teuchos::ScalarTraits::nan()), + // problem, tools + problem_(problem), + sm_(sorter), + om_(printer), + tester_(tester), + orthman_(ortho), + // timers, counters + timerOp_(Teuchos::TimeMonitor::getNewTimer("Operation Op*x")), + timerMOp_(Teuchos::TimeMonitor::getNewTimer("Operation M*x")), + timerPrec_(Teuchos::TimeMonitor::getNewTimer("Operation Prec*x")), + timerSortEval_(Teuchos::TimeMonitor::getNewTimer("Sorting eigenvalues")), + timerDS_(Teuchos::TimeMonitor::getNewTimer("Direct solve")), + timerLocal_(Teuchos::TimeMonitor::getNewTimer("Local update")), + timerCompRes_(Teuchos::TimeMonitor::getNewTimer("Computing residuals")), + timerOrtho_(Teuchos::TimeMonitor::getNewTimer("Orthogonalization")), + timerInit_(Teuchos::TimeMonitor::getNewTimer("Initialization")), + count_ApplyOp_(0), + count_ApplyM_(0), + count_ApplyPrec_(0), + // internal data + blockSize_(0), + numBlocks_(0), + initialized_(false), + curDim_(0), + auxVecs_( Teuchos::Array >(0) ), + numAuxVecs_(0), + iter_(0), + Rnorms_current_(false), + R2norms_current_(false) + { + TEST_FOR_EXCEPTION(problem_ == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavidson::constructor: user passed null problem pointer."); + TEST_FOR_EXCEPTION(sm_ == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavidson::constructor: user passed null sort manager pointer."); + TEST_FOR_EXCEPTION(om_ == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavidson::constructor: user passed null output manager pointer."); + TEST_FOR_EXCEPTION(tester_ == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavidson::constructor: user passed null status test pointer."); + TEST_FOR_EXCEPTION(orthman_ == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavidson::constructor: user passed null orthogonalization manager pointer."); + TEST_FOR_EXCEPTION(problem_->isProblemSet() == false, std::invalid_argument, + "Anasazi::BlockDavidson::constructor: problem is not set."); + TEST_FOR_EXCEPTION(problem_->isHermitian() == false, std::invalid_argument, + "Anasazi::BlockDavidson::constructor: problem is not hermitian."); + + // get the problem operators + Op_ = problem_->getOperator(); + TEST_FOR_EXCEPTION(Op_ == Teuchos::null, std::invalid_argument, + "Anasazi::BlockDavidson::constructor: problem provides no operator."); + MOp_ = problem_->getM(); + Prec_ = problem_->getPrec(); + hasM_ = (MOp_ != Teuchos::null); + + // set the block size and allocate data + int bs = params.get("Block Size", problem_->getNEV()); + int nb = params.get("Num Blocks", 2); + setSize(bs,nb); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Destructor + template + BlockDavidson::~BlockDavidson() {} + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the block size + // This simply calls setSize(), modifying the block size while retaining the number of blocks. + template + void BlockDavidson::setBlockSize (int blockSize) + { + setSize(blockSize,numBlocks_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Return the current auxiliary vectors + template + Teuchos::Array > BlockDavidson::getAuxVecs() const { + return auxVecs_; + } + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current block size + template + int BlockDavidson::getBlockSize() const { + return(blockSize_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return eigenproblem + template + const Eigenproblem& BlockDavidson::getProblem() const { + return(*problem_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return max subspace dim + template + int BlockDavidson::getMaxSubspaceDim() const { + return blockSize_*numBlocks_; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return current subspace dim + template + int BlockDavidson::getCurSubspaceDim() const { + if (!initialized_) return 0; + return curDim_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return ritz residual 2-norms + template + std::vector::magnitudeType> + BlockDavidson::getRitzRes2Norms() { + return this->getRes2Norms(); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return ritz index + template + std::vector BlockDavidson::getRitzIndex() { + std::vector ret(curDim_,0); + return ret; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return ritz values + template + std::vector > BlockDavidson::getRitzValues() { + std::vector > ret(curDim_); + for (int i=0; i + Teuchos::RCP BlockDavidson::getRitzVectors() { + return X_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // reset number of iterations + template + void BlockDavidson::resetNumIters() { + iter_=0; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return number of iterations + template + int BlockDavidson::getNumIters() const { + return(iter_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return state pointers + template + BlockDavidsonState BlockDavidson::getState() const { + BlockDavidsonState state; + state.curDim = curDim_; + state.V = V_; + state.X = X_; + state.KX = KX_; + if (hasM_) { + state.MX = MX_; + } + else { + state.MX = Teuchos::null; + } + state.R = R_; + state.H = H_; + state.KK = KK_; + if (curDim_ > 0) { + state.T = Teuchos::rcp(new std::vector(&theta_[0],&theta_[curDim_])); + } + else { + state.T = Teuchos::rcp(new std::vector(0)); + } + return state; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Return initialized state + template + bool BlockDavidson::isInitialized() const { return initialized_; } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the block size and make necessary adjustments. + template + void BlockDavidson::setSize (int blockSize, int numBlocks) + { + // time spent here counts towards timerInit_ + Teuchos::TimeMonitor lcltimer( *timerInit_ ); + + // This routine only allocates space; it doesn't not perform any computation + // any change in size will invalidate the state of the solver. + + TEST_FOR_EXCEPTION(blockSize < 1, std::invalid_argument, "Anasazi::BlockDavidson::setSize(blocksize,numblocks): blocksize must be strictly positive."); + TEST_FOR_EXCEPTION(numBlocks < 2, std::invalid_argument, "Anasazi::BlockDavidson::setSize(blocksize,numblocks): numblocks must be greater than one."); + if (blockSize == blockSize_ && numBlocks == numBlocks_) { + // do nothing + return; + } + + blockSize_ = blockSize; + numBlocks_ = numBlocks; + + Teuchos::RCP tmp; + // grab some Multivector to Clone + // in practice, getInitVec() should always provide this, but it is possible to use a + // Eigenproblem with nothing in getInitVec() by manually initializing with initialize(); + // in case of that strange scenario, we will try to Clone from X_ first, then resort to getInitVec() + if (X_ != Teuchos::null) { // this is equivalent to blockSize_ > 0 + tmp = X_; + } + else { + tmp = problem_->getInitVec(); + TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavidson::setSize(): eigenproblem did not specify initial vectors to clone from."); + } + + TEST_FOR_EXCEPTION(numAuxVecs_+blockSize*numBlocks > MVT::GetVecLength(*tmp),std::invalid_argument, + "Anasazi::BlockDavidson::setSize(): max subspace dimension and auxilliary subspace too large."); + + + ////////////////////////////////// + // blockSize dependent + // + // grow/allocate vectors + Rnorms_.resize(blockSize_,NANVAL); + R2norms_.resize(blockSize_,NANVAL); + // + // clone multivectors off of tmp + // + // free current allocation first, to make room for new allocation + X_ = Teuchos::null; + KX_ = Teuchos::null; + MX_ = Teuchos::null; + R_ = Teuchos::null; + V_ = Teuchos::null; + + om_->print(Debug," >> Allocating X_\n"); + X_ = MVT::Clone(*tmp,blockSize_); + om_->print(Debug," >> Allocating KX_\n"); + KX_ = MVT::Clone(*tmp,blockSize_); + if (hasM_) { + om_->print(Debug," >> Allocating MX_\n"); + MX_ = MVT::Clone(*tmp,blockSize_); + } + else { + MX_ = X_; + } + om_->print(Debug," >> Allocating R_\n"); + R_ = MVT::Clone(*tmp,blockSize_); + + ////////////////////////////////// + // blockSize*numBlocks dependent + // + int newsd = blockSize_*numBlocks_; + theta_.resize(blockSize_*numBlocks_,NANVAL); + om_->print(Debug," >> Allocating V_\n"); + V_ = MVT::Clone(*tmp,newsd); + KK_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix(newsd,newsd) ); + + om_->print(Debug," >> done allocating.\n"); + + initialized_ = false; + curDim_ = 0; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the auxiliary vectors + template + void BlockDavidson::setAuxVecs(const Teuchos::Array > &auxvecs) { + typedef typename Teuchos::Array >::iterator tarcpmv; + + // set new auxiliary vectors + auxVecs_ = auxvecs; + numAuxVecs_ = 0; + for (tarcpmv i=auxVecs_.begin(); i != auxVecs_.end(); ++i) { + numAuxVecs_ += MVT::GetNumberVecs(**i); + } + + // If the solver has been initialized, V is not necessarily orthogonal to new auxiliary vectors + if (numAuxVecs_ > 0 && initialized_) { + initialized_ = false; + } + + if (om_->isVerbosity( Debug ) ) { + CheckList chk; + chk.checkQ = true; + om_->print( Debug, accuracyCheck(chk, ": in setAuxVecs()") ); + } + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + /* Initialize the state of the solver + * + * POST-CONDITIONS: + * + * V_ is orthonormal, orthogonal to auxVecs_, for first curDim_ vectors + * theta_ contains Ritz w.r.t. V_(1:curDim_) + * X is Ritz vectors w.r.t. V_(1:curDim_) + * KX = Op*X + * MX = M*X if hasM_ + * R = KX - MX*diag(theta_) + * + */ + template + void BlockDavidson::initialize(BlockDavidsonState newstate) + { + // NOTE: memory has been allocated by setBlockSize(). Use setBlock below; do not Clone + // NOTE: Overall time spent in this routine is counted to timerInit_; portions will also be counted towards other primitives + + Teuchos::TimeMonitor lcltimer( *timerInit_ ); + + std::vector bsind(blockSize_); + for (int i=0; i blas; + + // in BlockDavidson, V is primary + // the order of dependence follows like so. + // --init-> V,KK + // --ritz analysis-> theta,X + // --op apply-> KX,MX + // --compute-> R + // + // if the user specifies all data for a level, we will accept it. + // otherwise, we will generate the whole level, and all subsequent levels. + // + // the data members are ordered based on dependence, and the levels are + // partitioned according to the amount of work required to produce the + // items in a level. + // + // inconsistent multivectors widths and lengths will not be tolerated, and + // will be treated with exceptions. + // + // for multivector pointers in newstate which point directly (as opposed to indirectly, via a view) to + // multivectors in the solver, the copy will not be affected. + + // set up V and KK: get them from newstate if user specified them + // otherwise, set them manually + Teuchos::RCP lclV; + Teuchos::RCP > lclKK; + + if (newstate.V != Teuchos::null && newstate.KK != Teuchos::null) { + TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.V) != MVT::GetVecLength(*V_), std::invalid_argument, + "Anasazi::BlockDavidson::initialize(newstate): Vector length of V not correct." ); + TEST_FOR_EXCEPTION( newstate.curDim < blockSize_, std::invalid_argument, + "Anasazi::BlockDavidson::initialize(newstate): Rank of new state must be at least blockSize()."); + TEST_FOR_EXCEPTION( newstate.curDim > blockSize_*numBlocks_, std::invalid_argument, + "Anasazi::BlockDavidson::initialize(newstate): Rank of new state must be less than getMaxSubspaceDim()."); + TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.V) < newstate.curDim, std::invalid_argument, + "Anasazi::BlockDavidson::initialize(newstate): Multivector for basis in new state must be as large as specified state rank."); + + curDim_ = newstate.curDim; + // pick an integral amount + curDim_ = (int)(curDim_ / blockSize_)*blockSize_; + + TEST_FOR_EXCEPTION( curDim_ != newstate.curDim, std::invalid_argument, + "Anasazi::BlockDavidson::initialize(newstate): Rank of new state must be a multiple of getBlockSize()."); + + // check size of KK + TEST_FOR_EXCEPTION( newstate.KK->numRows() < curDim_ || newstate.KK->numCols() < curDim_, std::invalid_argument, + "Anasazi::BlockDavidson::initialize(newstate): Projected matrix in new state must be as large as specified state rank."); + + + // put data in V + std::vector nevind(curDim_); + for (int i=0; i(Teuchos::View,*KK_,curDim_,curDim_) ); + if (newstate.KK != KK_) { + Teuchos::SerialDenseMatrix newKK(Teuchos::View,*newstate.KK,curDim_,curDim_); + lclKK->assign(newKK); + } + // + // make lclKK Hermitian in memory (copy the upper half to the lower half) + for (int j=0; j ivec = problem_->getInitVec(); + TEST_FOR_EXCEPTION(ivec == Teuchos::null,std::invalid_argument, + "Anasazi::BlockDavdison::initialize(newstate): Eigenproblem did not specify initial vectors to clone from."); + // clear newstate so we won't use any data from it below + newstate.X = Teuchos::null; + newstate.MX = Teuchos::null; + newstate.KX = Teuchos::null; + newstate.R = Teuchos::null; + newstate.H = Teuchos::null; + newstate.T = Teuchos::null; + newstate.KK = Teuchos::null; + newstate.V = Teuchos::null; + newstate.curDim = 0; + + curDim_ = MVT::GetNumberVecs(*ivec); + // pick the largest multiple of blockSize_ + curDim_ = (int)(curDim_ / blockSize_)*blockSize_; + if (curDim_ > blockSize_*numBlocks_) { + // user specified too many vectors... truncate + // this produces a full subspace, but that is okay + curDim_ = blockSize_*numBlocks_; + } + bool userand = false; + if (curDim_ == 0) { + // we need at least blockSize_ vectors + // use a random multivec: ignore everything from InitVec + userand = true; + curDim_ = blockSize_; + } + + // get pointers into V,KV,MV + // tmpVecs will be used below for M*V and K*V (not simultaneously) + // lclV has curDim vectors + // if there is space for lclV and tmpVecs in V_, point tmpVecs into V_ + // otherwise, we must allocate space for these products + // + // get pointer to first curDim vector in V_ + std::vector dimind(curDim_); + for (int i=0; i tmpVecs; + if (curDim_*2 <= blockSize_*numBlocks_) { + // partition V_ = [lclV tmpVecs _leftover_] + std::vector block2(curDim_); + for (int i=0; i 0) { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + + Teuchos::Array > > dummy; + int rank = orthman_->projectAndNormalizeMat(*lclV,tmpVecs,dummy,Teuchos::null,auxVecs_); + TEST_FOR_EXCEPTION(rank != curDim_,BlockDavidsonInitFailure, + "Anasazi::BlockDavidson::initialize(): Couldn't generate initial basis of full rank."); + } + else { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + + int rank = orthman_->normalizeMat(*lclV,tmpVecs,Teuchos::null); + TEST_FOR_EXCEPTION(rank != curDim_,BlockDavidsonInitFailure, + "Anasazi::BlockDavidson::initialize(): Couldn't generate initial basis of full rank."); + } + + // compute K*lclV: we are re-using tmpVecs to store the result + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*Op_,*lclV,*tmpVecs); + count_ApplyOp_ += curDim_; + } + + // generate KK + lclKK = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::View,*KK_,curDim_,curDim_) ); + MVT::MvTransMv(ONE,*lclV,*tmpVecs,*lclKK); + + // clear tmpVecs + tmpVecs = Teuchos::null; + } + + // X,theta require Ritz analysis; if we have to generate one of these, we might as well generate both + if (newstate.X != Teuchos::null && newstate.T != Teuchos::null) { + TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*newstate.X) != blockSize_ || MVT::GetVecLength(*newstate.X) != MVT::GetVecLength(*X_), + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): Size of X must be consistent with block size and length of V."); + TEST_FOR_EXCEPTION((signed int)(newstate.T->size()) != curDim_, + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): Size of T must be consistent with dimension of V."); + + if (newstate.X != X_) { + MVT::SetBlock(*newstate.X,bsind,*X_); + } + + std::copy(newstate.T->begin(),newstate.T->end(),theta_.begin()); + } + else { + // compute ritz vecs/vals + Teuchos::SerialDenseMatrix S(curDim_,curDim_); + { + Teuchos::TimeMonitor lcltimer( *timerDS_ ); + int rank = curDim_; + Utils::directSolver(curDim_, *lclKK, Teuchos::null, S, theta_, rank, 10); + // we want all ritz values back + TEST_FOR_EXCEPTION(rank != curDim_,BlockDavidsonInitFailure, + "Anasazi::BlockDavidson::initialize(newstate): Not enough Ritz vectors to initialize algorithm."); + } + // sort ritz pairs + { + Teuchos::TimeMonitor lcltimer( *timerSortEval_ ); + + std::vector order(curDim_); + // + // sort the first curDim_ values in theta_ + sm_->sort( this, curDim_, theta_, &order ); // don't catch exception + // + // apply the same ordering to the primitive ritz vectors + Utils::permuteVectors(order,S); + } + + // compute eigenvectors + Teuchos::SerialDenseMatrix S1(Teuchos::View,S,curDim_,blockSize_); + { + Teuchos::TimeMonitor lcltimer( *timerLocal_ ); + + // X <- lclV*S + MVT::MvTimesMatAddMv( ONE, *lclV, S1, ZERO, *X_ ); + } + // we generated theta,X so we don't want to use the user's KX,MX + newstate.KX = Teuchos::null; + newstate.MX = Teuchos::null; + } + + // done with local pointers + lclV = Teuchos::null; + lclKK = Teuchos::null; + + // set up KX + if ( newstate.KX != Teuchos::null ) { + TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*newstate.KX) != blockSize_, + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): vector length of newstate.KX not correct." ); + TEST_FOR_EXCEPTION(MVT::GetVecLength(*newstate.KX) != MVT::GetVecLength(*X_), + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): newstate.KX must have at least block size vectors." ); + if (newstate.KX != KX_) { + MVT::SetBlock(*newstate.KX,bsind,*KX_); + } + } + else { + // generate KX + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*Op_,*X_,*KX_); + count_ApplyOp_ += blockSize_; + } + // we generated KX; we will generate R as well + newstate.R = Teuchos::null; + } + + // set up MX + if (hasM_) { + if ( newstate.MX != Teuchos::null ) { + TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*newstate.MX) != blockSize_, + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): vector length of newstate.MX not correct." ); + TEST_FOR_EXCEPTION(MVT::GetVecLength(*newstate.MX) != MVT::GetVecLength(*X_), + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): newstate.MX must have at least block size vectors." ); + if (newstate.MX != MX_) { + MVT::SetBlock(*newstate.MX,bsind,*MX_); + } + } + else { + // generate MX + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*MOp_,*X_,*MX_); + count_ApplyOp_ += blockSize_; + } + // we generated MX; we will generate R as well + newstate.R = Teuchos::null; + } + } + else { + // the assignment MX_==X_ would be redundant; take advantage of this opportunity to debug a little + TEST_FOR_EXCEPTION(MX_ != X_, std::logic_error, "Anasazi::BlockDavidson::initialize(): solver invariant not satisfied (MX==X)."); + } + + // set up R + if (newstate.R != Teuchos::null) { + TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*newstate.R) != blockSize_, + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): vector length of newstate.R not correct." ); + TEST_FOR_EXCEPTION(MVT::GetVecLength(*newstate.R) != MVT::GetVecLength(*X_), + std::invalid_argument, "Anasazi::BlockDavidson::initialize(newstate): newstate.R must have at least block size vectors." ); + if (newstate.R != R_) { + MVT::SetBlock(*newstate.R,bsind,*R_); + } + } + else { + Teuchos::TimeMonitor lcltimer( *timerCompRes_ ); + + // form R <- KX - MX*T + MVT::MvAddMv(ZERO,*KX_,ONE,*KX_,*R_); + Teuchos::SerialDenseMatrix T(blockSize_,blockSize_); + T.putScalar(ZERO); + for (int i=0; iisVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkV = true; + chk.checkX = true; + chk.checkKX = true; + chk.checkMX = true; + chk.checkR = true; + chk.checkQ = true; + chk.checkKK = true; + om_->print( Debug, accuracyCheck(chk, ": after initialize()") ); + } + + // Print information on current status + if (om_->isVerbosity(Debug)) { + currentStatus( om_->stream(Debug) ); + } + else if (om_->isVerbosity(IterationDetails)) { + currentStatus( om_->stream(IterationDetails) ); + } + + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // initialize the solver with default state + template + void BlockDavidson::initialize() + { + BlockDavidsonState empty; + initialize(empty); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Perform BlockDavidson iterations until the StatusTest tells us to stop. + template + void BlockDavidson::iterate () + { + // + // Initialize solver state + if (initialized_ == false) { + initialize(); + } + + // as a data member, this would be redundant and require synchronization with + // blockSize_ and numBlocks_; we'll use a constant here. + const int searchDim = blockSize_*numBlocks_; + + Teuchos::BLAS blas; + + // + // The projected matrices are part of the state, but the eigenvectors are defined locally. + // S = Local eigenvectors (size: searchDim * searchDim + Teuchos::SerialDenseMatrix S( searchDim, searchDim ); + + + //////////////////////////////////////////////////////////////// + // iterate until the status test tells us to stop. + // also break if our basis is full + while (tester_->checkStatus(this) != Passed && curDim_ < searchDim) { + + // Print information on current iteration + if (om_->isVerbosity(Debug)) { + currentStatus( om_->stream(Debug) ); + } + else if (om_->isVerbosity(IterationDetails)) { + currentStatus( om_->stream(IterationDetails) ); + } + + ++iter_; + + // get the current part of the basis + std::vector curind(blockSize_); + for (int i=0; i bsind(blockSize_); + for (int i=0; i prevind(curDim_); + for (int i=0; i Vprev = MVT::CloneView(*V_,prevind); + + // Orthogonalize H against the previous vectors and the auxiliary vectors, and normalize + { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + + Teuchos::Array > against = auxVecs_; + against.push_back(Vprev); + int rank = orthman_->projectAndNormalizeMat(*H_,MH_, + Teuchos::tuple > >(Teuchos::null), + Teuchos::null,against); + TEST_FOR_EXCEPTION(rank != blockSize_,BlockDavidsonOrthoFailure, + "Anasazi::BlockDavidson::iterate(): unable to compute orthonormal basis for H."); + } + + // Apply the stiffness matrix to H + { + // use memory at KX_ for temporary storage + KH_ = KX_; + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply( *Op_, *H_, *KH_); // don't catch the exception + count_ApplyOp_ += blockSize_; + } + + if (om_->isVerbosity( Debug ) ) { + CheckList chk; + chk.checkH = true; + chk.checkMH = true; + chk.checkKH = true; + om_->print( Debug, accuracyCheck(chk, ": after ortho H") ); + } + else if (om_->isVerbosity( OrthoDetails ) ) { + CheckList chk; + chk.checkH = true; + chk.checkMH = true; + chk.checkKH = true; + om_->print( OrthoDetails, accuracyCheck(chk,": after ortho H") ); + } + + // compute next part of the projected matrices + // this this in two parts + Teuchos::RCP > nextKK; + // Vprev*K*H + nextKK = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::View,*KK_,curDim_,blockSize_,0,curDim_) ); + MVT::MvTransMv(ONE,*Vprev,*KH_,*nextKK); + // H*K*H + nextKK = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::View,*KK_,blockSize_,blockSize_,curDim_,curDim_) ); + MVT::MvTransMv(ONE,*H_,*KH_,*nextKK); + // + // make sure that KK_ is Hermitian in memory + nextKK = Teuchos::null; + for (int i=curDim_; iisVerbosity( Debug ) ) { + CheckList chk; + chk.checkKK = true; + om_->print( Debug, accuracyCheck(chk, ": after expanding KK") ); + } + + // Get pointer to complete basis + curind.resize(curDim_); + for (int i=0; i curV = MVT::CloneView(*V_,curind); + + // Perform spectral decomposition + { + Teuchos::TimeMonitor lcltimer(*timerDS_); + int nevlocal = curDim_; + int info = Utils::directSolver(curDim_,*KK_,Teuchos::null,S,theta_,nevlocal,10); + TEST_FOR_EXCEPTION(info != 0,std::logic_error,"Anasazi::BlockDavidson::iterate(): direct solve returned error code."); + // we did not ask directSolver to perform deflation, so nevLocal better be curDim_ + TEST_FOR_EXCEPTION(nevlocal != curDim_,std::logic_error,"Anasazi::BlockDavidson::iterate(): direct solve did not compute all eigenvectors."); // this should never happen + } + + // Sort ritz pairs + { + Teuchos::TimeMonitor lcltimer( *timerSortEval_ ); + + std::vector order(curDim_); + // + // sort the first curDim_ values in theta_ + sm_->sort( this, curDim_, theta_, &order ); // don't catch exception + // + // apply the same ordering to the primitive ritz vectors + Teuchos::SerialDenseMatrix curS(Teuchos::View,S,curDim_,curDim_); + Utils::permuteVectors(order,curS); + } + + // Create a view matrix of the first blockSize_ vectors + Teuchos::SerialDenseMatrix S1( Teuchos::View, S, curDim_, blockSize_ ); + + // Compute the new Ritz vectors + { + Teuchos::TimeMonitor lcltimer( *timerLocal_ ); + MVT::MvTimesMatAddMv(ONE,*curV,S1,ZERO,*X_); + } + + // Apply the stiffness matrix for the Ritz vectors + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply( *Op_, *X_, *KX_); // don't catch the exception + count_ApplyOp_ += blockSize_; + } + // Apply the mass matrix for the Ritz vectors + if (hasM_) { + Teuchos::TimeMonitor lcltimer( *timerMOp_ ); + OPT::Apply(*MOp_,*X_,*MX_); + count_ApplyM_ += blockSize_; + } + else { + MX_ = X_; + } + + // Compute the residual + // R = KX - MX*diag(theta) + { + Teuchos::TimeMonitor lcltimer( *timerCompRes_ ); + + MVT::MvAddMv( ONE, *KX_, ZERO, *KX_, *R_ ); + Teuchos::SerialDenseMatrix T( blockSize_, blockSize_ ); + for (int i = 0; i < blockSize_; ++i) { + T(i,i) = theta_[i]; + } + MVT::MvTimesMatAddMv( -ONE, *MX_, T, ONE, *R_ ); + } + + // R has been updated; mark the norms as out-of-date + Rnorms_current_ = false; + R2norms_current_ = false; + + + // When required, monitor some orthogonalities + if (om_->isVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkV = true; + chk.checkX = true; + chk.checkKX = true; + chk.checkMX = true; + chk.checkR = true; + om_->print( Debug, accuracyCheck(chk, ": after local update") ); + } + else if (om_->isVerbosity( OrthoDetails )) { + CheckList chk; + chk.checkX = true; + chk.checkKX = true; + chk.checkMX = true; + chk.checkR = true; + om_->print( OrthoDetails, accuracyCheck(chk, ": after local update") ); + } + } // end while (statusTest == false) + + } // end of iterate() + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // compute/return residual M-norms + template + std::vector::magnitudeType> + BlockDavidson::getResNorms() { + if (Rnorms_current_ == false) { + // Update the residual norms + orthman_->norm(*R_,&Rnorms_); + Rnorms_current_ = true; + } + return Rnorms_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // compute/return residual 2-norms + template + std::vector::magnitudeType> + BlockDavidson::getRes2Norms() { + if (R2norms_current_ == false) { + // Update the residual 2-norms + MVT::MvNorm(*R_,&R2norms_); + R2norms_current_ = true; + } + return R2norms_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Check accuracy, orthogonality, and other debugging stuff + // + // bools specify which tests we want to run (instead of running more than we actually care about) + // + // we don't bother checking the following because they are computed explicitly: + // H == Prec*R + // KH == K*H + // + // + // checkV : V orthonormal + // orthogonal to auxvecs + // checkX : X orthonormal + // orthogonal to auxvecs + // checkMX: check MX == M*X + // checkKX: check KX == K*X + // checkH : H orthonormal + // orthogonal to V and H and auxvecs + // checkMH: check MH == M*H + // checkR : check R orthogonal to X + // checkQ : check that auxiliary vectors are actually orthonormal + // checkKK: check that KK is symmetric in memory + // + // TODO: + // add checkTheta + // + template + std::string BlockDavidson::accuracyCheck( const CheckList &chk, const std::string &where ) const + { + using std::endl; + + std::stringstream os; + os.precision(2); + os.setf(std::ios::scientific, std::ios::floatfield); + MagnitudeType tmp; + + os << " Debugging checks: iteration " << iter_ << where << endl; + + // V and friends + std::vector lclind(curDim_); + for (int i=0; i lclV,lclKV; + if (initialized_) { + lclV = MVT::CloneView(*V_,lclind); + } + if (chk.checkV && initialized_) { + tmp = orthman_->orthonormError(*lclV); + os << " >> Error in V^H M V == I : " << tmp << endl; + for (unsigned int i=0; iorthogError(*lclV,*auxVecs_[i]); + os << " >> Error in V^H M Q[" << i << "] == 0 : " << tmp << endl; + } + Teuchos::SerialDenseMatrix curKK(curDim_,curDim_); + Teuchos::RCP lclKV = MVT::Clone(*V_,curDim_); + OPT::Apply(*Op_,*lclV,*lclKV); + MVT::MvTransMv(ONE,*lclV,*lclKV,curKK); + Teuchos::SerialDenseMatrix subKK(Teuchos::View,*KK_,curDim_,curDim_); + curKK -= subKK; + // dup the lower tri part + for (int j=0; j> Error in V^H K V == KK : " << curKK.normFrobenius() << endl; + } + + // X and friends + if (chk.checkX && initialized_) { + tmp = orthman_->orthonormError(*X_); + os << " >> Error in X^H M X == I : " << tmp << endl; + for (unsigned int i=0; iorthogError(*X_,*auxVecs_[i]); + os << " >> Error in X^H M Q[" << i << "] == 0 : " << tmp << endl; + } + } + if (chk.checkMX && hasM_ && initialized_) { + tmp = Utils::errorEquality(*X_, *MX_, MOp_); + os << " >> Error in MX == M*X : " << tmp << endl; + } + if (chk.checkKX && initialized_) { + tmp = Utils::errorEquality(*X_, *KX_, Op_); + os << " >> Error in KX == K*X : " << tmp << endl; + } + + // H and friends + if (chk.checkH && initialized_) { + tmp = orthman_->orthonormError(*H_); + os << " >> Error in H^H M H == I : " << tmp << endl; + tmp = orthman_->orthogError(*H_,*lclV); + os << " >> Error in H^H M V == 0 : " << tmp << endl; + tmp = orthman_->orthogError(*H_,*X_); + os << " >> Error in H^H M X == 0 : " << tmp << endl; + for (unsigned int i=0; iorthogError(*H_,*auxVecs_[i]); + os << " >> Error in H^H M Q[" << i << "] == 0 : " << tmp << endl; + } + } + if (chk.checkKH && initialized_) { + tmp = Utils::errorEquality(*H_, *KH_, Op_); + os << " >> Error in KH == K*H : " << tmp << endl; + } + if (chk.checkMH && hasM_ && initialized_) { + tmp = Utils::errorEquality(*H_, *MH_, MOp_); + os << " >> Error in MH == M*H : " << tmp << endl; + } + + // R: this is not M-orthogonality, but standard Euclidean orthogonality + if (chk.checkR && initialized_) { + Teuchos::SerialDenseMatrix xTx(blockSize_,blockSize_); + MVT::MvTransMv(ONE,*X_,*R_,xTx); + tmp = xTx.normFrobenius(); + os << " >> Error in X^H R == 0 : " << tmp << endl; + } + + // KK + if (chk.checkKK && initialized_) { + Teuchos::SerialDenseMatrix tmp(curDim_,curDim_), lclKK(Teuchos::View,*KK_,curDim_,curDim_); + for (int j=0; j> Error in KK - KK^H == 0 : " << tmp.normFrobenius() << endl; + } + + // Q + if (chk.checkQ) { + for (unsigned int i=0; iorthonormError(*auxVecs_[i]); + os << " >> Error in Q[" << i << "]^H M Q[" << i << "] == I : " << tmp << endl; + for (unsigned int j=i+1; jorthogError(*auxVecs_[i],*auxVecs_[j]); + os << " >> Error in Q[" << i << "]^H M Q[" << j << "] == 0 : " << tmp << endl; + } + } + } + + os << endl; + + return os.str(); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Print the current status of the solver + template + void + BlockDavidson::currentStatus(std::ostream &os) + { + using std::endl; + + os.setf(std::ios::scientific, std::ios::floatfield); + os.precision(6); + os < +class BlockDavidsonSolMgr : public SolverManager { + + private: + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + typedef Teuchos::ScalarTraits SCT; + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + public: + + //! @name Constructors/Destructor + //@{ + + /*! \brief Basic constructor for BlockDavidsonSolMgr. + * + * This constructor accepts the Eigenproblem to be solved in addition + * to a parameter list of options for the solver manager. These options include the following: + * - "Which" - a \c string specifying the desired eigenvalues: SM, LM, SR or LR. Default: "SR" + * - "Block Size" - a \c int specifying the block size to be used by the underlying block Davidson solver. Default: problem->getNEV() + * - "Num Blocks" - a \c int specifying the number of blocks allocated for the Krylov basis. Default: 2 + * - "Maximum Restarts" - a \c int specifying the maximum number of restarts the underlying solver is allowed to perform. Default: 20 + * - "Verbosity" - a sum of MsgType specifying the verbosity. Default: Anasazi::Errors + * - "Convergence Tolerance" - a \c MagnitudeType specifying the level that residual norms must reach to decide convergence. Default: machine precision. + * - "Relative Convergence Tolerance" - a \c bool specifying whether residuals norms should be scaled by their eigenvalues for the purposing of deciding convergence. Default: true + * - "Use Locking" - a \c bool specifying whether the algorithm should employ locking of converged eigenpairs. Default: false + * - "Max Locked" - a \c int specifying the maximum number of eigenpairs to be locked. Default: problem->getNEV() + * - "Locking Quorum" - a \c int specifying the number of eigenpairs that must meet the locking criteria before locking actually occurs. Default: 1 + * - "Locking Tolerance" - a \c MagnitudeType specifying the level that residual norms must reach to decide locking. Default: 0.1*convergence tolerance + * - "Relative Locking Tolerance" - a \c bool specifying whether residuals norms should be scaled by their eigenvalues for the purposing of deciding locking. Default: true + */ + BlockDavidsonSolMgr( const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ); + + //! Destructor. + virtual ~BlockDavidsonSolMgr() {}; + //@} + + //! @name Accessor methods + //@{ + + const Eigenproblem& getProblem() const { + return *problem_; + } + + //@} + + //! @name Solver application methods + //@{ + + /*! \brief This method performs possibly repeated calls to the underlying eigensolver's iterate() routine + * until the problem has been solved (as decided by the solver manager) or the solver manager decides to + * quit. + * + * This method calls BlockDavidson::iterate(), which will return either because a specially constructed status test evaluates to ::Passed + * or an exception is thrown. + * + * A return from BlockDavidson::iterate() signifies one of the following scenarios: + * - the maximum number of restarts has been exceeded. In this scenario, the solver manager will place\n + * all converged eigenpairs into the eigenproblem and return ::Unconverged. + * - the locking conditions have been met. In this scenario, some of the current eigenpairs will be removed\n + * from the eigensolver and placed into auxiliary storage. The eigensolver will be restarted with the remaining part of the Krylov subspace\n + * and some random information to replace the removed subspace. + * - global convergence has been met. In this case, the most significant NEV eigenpairs in the solver and locked storage \n + * have met the convergence criterion. (Here, NEV refers to the number of eigenpairs requested by the Eigenproblem.) \n + * In this scenario, the solver manager will return ::Converged. + * + * \returns ::ReturnType specifying: + * - ::Converged: the eigenproblem was solved to the specification required by the solver manager. + * - ::Unconverged: the eigenproblem was not solved to the specification desired by the solver manager. + */ + ReturnType solve(); + //@} + + private: + Teuchos::RCP > problem_; + + std::string whch_; + + MagnitudeType convtol_, locktol_; + int maxRestarts_; + bool useLocking_; + bool relconvtol_, rellocktol_; + int blockSize_, numBlocks_; + int maxLocked_; + int verbosity_; + int lockQuorum_; + bool inSituRestart_; + int numRestartBlocks_; +}; + + +// Constructor +template +BlockDavidsonSolMgr::BlockDavidsonSolMgr( + const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ) : + problem_(problem), + whch_("SR"), + convtol_(0), + locktol_(0), + maxRestarts_(20), + useLocking_(false), + relconvtol_(true), + rellocktol_(true), + blockSize_(0), + numBlocks_(0), + maxLocked_(0), + verbosity_(Anasazi::Errors), + lockQuorum_(1), + inSituRestart_(false), + numRestartBlocks_(1) +{ + TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager."); + TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set."); + TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric."); + TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null, std::invalid_argument, "Problem does not contain initial vectors to clone from."); + + // which values to solve for + whch_ = pl.get("Which",whch_); + TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR",std::invalid_argument, "Invalid sorting string."); + + // convergence tolerance + convtol_ = pl.get("Convergence Tolerance",MT::prec()); + relconvtol_ = pl.get("Relative Convergence Tolerance",relconvtol_); + + // locking tolerance + useLocking_ = pl.get("Use Locking",useLocking_); + rellocktol_ = pl.get("Relative Locking Tolerance",rellocktol_); + locktol_ = pl.get("Locking Tolerance",convtol_/10.0); + + // maximum number of restarts + maxRestarts_ = pl.get("Maximum Restarts",maxRestarts_); + + // block size: default is nev() + blockSize_ = pl.get("Block Size",problem_->getNEV()); + TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: \"Block Size\" must be strictly positive."); + numBlocks_ = pl.get("Num Blocks",2); + TEST_FOR_EXCEPTION(numBlocks_ <= 1, std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: \"Num Blocks\" must be >= 1."); + + // max locked: default is nev(), must satisfy maxLocked_ + blockSize_ >= nev + if (useLocking_) { + maxLocked_ = pl.get("Max Locked",problem_->getNEV()); + } + else { + maxLocked_ = 0; + } + if (maxLocked_ == 0) { + useLocking_ = false; + } + TEST_FOR_EXCEPTION(maxLocked_ < 0, std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: \"Max Locked\" must be positive."); + TEST_FOR_EXCEPTION(maxLocked_ + blockSize_ < problem_->getNEV(), + std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: Not enough storage space for requested number of eigenpairs."); + TEST_FOR_EXCEPTION(numBlocks_*blockSize_ + maxLocked_ > MVT::GetVecLength(*problem_->getInitVec()), + std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: Potentially impossible orthogonality requests. Reduce basis size or locking size."); + + if (useLocking_) { + lockQuorum_ = pl.get("Locking Quorum",lockQuorum_); + TEST_FOR_EXCEPTION(lockQuorum_ <= 0, + std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: \"Locking Quorum\" must be strictly positive."); + } + + // verbosity level + if (pl.isParameter("Verbosity")) { + if (Teuchos::isParameterType(pl,"Verbosity")) { + verbosity_ = pl.get("Verbosity", verbosity_); + } else { + verbosity_ = (int)Teuchos::getParameter(pl,"Verbosity"); + } + } + + // restart size + numRestartBlocks_ = pl.get("Num Restart Blocks",numRestartBlocks_); + TEST_FOR_EXCEPTION(numRestartBlocks_ <= 0, std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: \"Num Restart Blocks\" must be strictly positive."); + TEST_FOR_EXCEPTION(numRestartBlocks_ >= numBlocks_, std::invalid_argument, + "Anasazi::BlockDavidsonSolMgr: \"Num Restart Blocks\" must be strictly less than \"Num Blocks\"."); + + // restarting technique: V*Q or applyHouse(V,H,tau) + if (pl.isParameter("In Situ Restarting")) { + if (Teuchos::isParameterType(pl,"In Situ Restarting")) { + inSituRestart_ = pl.get("In Situ Restarting",inSituRestart_); + } else { + inSituRestart_ = (bool)Teuchos::getParameter(pl,"In Situ Restarting"); + } + } +} + + +// solve() +template +ReturnType +BlockDavidsonSolMgr::solve() { + + typedef SolverUtils msutils; + + const int nev = problem_->getNEV(); + + ////////////////////////////////////////////////////////////////////////////////////// + // Sort manager + Teuchos::RCP > sorter = Teuchos::rcp( new BasicSort(whch_) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Output manager + Teuchos::RCP > printer = Teuchos::rcp( new BasicOutputManager(verbosity_) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Status tests + // + // convergence + Teuchos::RCP > convtest + = Teuchos::rcp( new StatusTestOrderedResNorm(sorter,convtol_,nev,StatusTestOrderedResNorm::RES_ORTH,relconvtol_) ); + // locking + Teuchos::RCP > locktest; + if (useLocking_) { + locktest = Teuchos::rcp( new StatusTestResNorm(locktol_,lockQuorum_,StatusTestResNorm::RES_ORTH,rellocktol_) ); + } + // combo class + Teuchos::Array > > alltests; + // for an OR test, the order doesn't matter + alltests.push_back(convtest); + if (locktest != Teuchos::null) alltests.push_back(locktest); + // combo: convergence || locking + Teuchos::RCP > combotest + = Teuchos::rcp( new StatusTestCombo( StatusTestCombo::OR, alltests) ); + // printing StatusTest + Teuchos::RCP > outputtest + = Teuchos::rcp( new StatusTestOutput( printer,combotest,1,Passed ) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Orthomanager + Teuchos::RCP > ortho + = Teuchos::rcp( new SVQBOrthoManager(problem_->getM()) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Parameter list + Teuchos::ParameterList plist; + plist.set("Block Size",blockSize_); + plist.set("Num Blocks",numBlocks_); + + ////////////////////////////////////////////////////////////////////////////////////// + // BlockDavidson solver + Teuchos::RCP > bd_solver + = Teuchos::rcp( new BlockDavidson(problem_,sorter,printer,outputtest,ortho,plist) ); + // set any auxiliary vectors defined in the problem + Teuchos::RCP< const MV > probauxvecs = problem_->getAuxVecs(); + if (probauxvecs != Teuchos::null) { + bd_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP >(probauxvecs) ); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // Storage + // for locked vectors + int curNumLocked = 0; + Teuchos::RCP lockvecs; + // lockvecs is used to hold the locked eigenvectors, as well as for temporary storage when locking. + // when locking, we will lock some number of vectors numnew, where numnew <= maxlocked - curlocked + // we will produce numnew random vectors, which will go into the space with the new basis. + // we will also need numnew storage for the image of these random vectors under A and M; + // columns [curlocked+1,curlocked+numnew] will be used for this storage + if (maxLocked_ > 0) { + lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_); + } + std::vector lockvals; + // + // Restarting occurs under two scenarios: when the basis is full and after locking. + // + // For the former, a new basis of size blockSize*numRestartBlocks is generated using the current basis + // and the most significant primitive Ritz vectors (projected eigenvectors). + // [S,L] = eig(KK) + // S = [Sr St] // some for "r"estarting, some are "t"runcated + // newV = V*Sr + // KK_new = newV'*K*newV = Sr'*V'*K*V*Sr = Sr'*KK*Sr + // Therefore, the only multivector operation needed is for the generation of newV. + // + // * If the multiplication is explicit, it requires a workspace of blockSize*numRestartBlocks vectors. + // This space must be specifically allocated for that task, as we don't have any space of that size. + // It (workMV) will be allocated at the beginning of solve() + // * Optionally, the multiplication can be performed implicitly, via a Householder QR factorization of + // Sr. This can be done in situ, using the basis multivector contained in the solver. This requires + // that we cast away the const on the multivector returned from getState(). Workspace for this approach + // is a single vector. the solver's internal storage must be preserved (X,MX,KX,R), requiring us to + // allocate this vector. + // + // For the latter (restarting after locking), the new basis is the same size as existing basis. If numnew + // vectors are locked, they are deflated from the current basis and replaced with randomly generated + // vectors. + // [S,L] = eig(KK) + // S = [Sl Su] // partitioned: "l"ocked and "u"nlocked + // newL = V*Sl = X(locked) + // defV = V*Su + // augV = rand(numnew) // orthogonal to oldL,newL,defV,auxvecs + // newV = [defV augV] + // Kknew = newV'*K*newV = [Su'*KK*Su defV'*K*augV] + // [augV'*K*defV augV'*K*augV] + // locked = [oldL newL] + // Clearly, this operation is more complicated than the previous. + // Here is a list of the significant computations that need to be performed: + // - newL will be put into space in lockvecs, but will be copied from getState().X at the end + // - defV,augV will be stored in workspace the size of the current basis. + // - If inSituRestart==true, we compute defV in situ in bd_solver::V_ and + // put augV at the end of bd_solver::V_ + // - If inSituRestart==false, we must have curDim vectors available for + // defV and augV; we will allocate a multivector (workMV) at the beginning of solve() + // for this purpose. + // - M*augV and K*augV are needed; they will be stored in lockvecs. As a result, newL will + // not be put into lockvecs until the end. + // + // Therefore, we must allocate workMV when ((maxRestarts_ > 0) || (useLocking_ == true)) && inSituRestart == false + // It will be allocated to size (numBlocks-1)*blockSize + // + Teuchos::RCP workMV; + if (inSituRestart_ == false) { + // we need storage space to restart, either if we may lock or if may restart after a full basis + if (useLocking_==true || maxRestarts_ > 0) { + workMV = MVT::Clone(*problem_->getInitVec(),(numBlocks_-1)*blockSize_); + } + else { + // we will never need to restart. + workMV = Teuchos::null; + } + } + else { // inSituRestart_ == true + // we will restart in situ, if we need to restart + // three situation remain: + // - never restart => no space needed + // - only restart for locking (i.e., never restart full) => no space needed + // - restart for full basis => need one vector + if (maxRestarts_ > 0) { + workMV = MVT::Clone(*problem_->getInitVec(),1); + } + else { + workMV = Teuchos::null; + } + } + + // some consts and utils + const ScalarType ONE = SCT::one(); + const ScalarType ZERO = SCT::zero(); + Teuchos::LAPACK lapack; + Teuchos::BLAS blas; + + // go ahead and initialize the solution to nothing in case we throw an exception + Eigensolution sol; + sol.numVecs = 0; + problem_->setSolution(sol); + + int numRestarts = 0; + + // tell bd_solver to iterate + while (1) { + try { + bd_solver->iterate(); + + //////////////////////////////////////////////////////////////////////////////////// + // + // check convergence first + // + //////////////////////////////////////////////////////////////////////////////////// + if (convtest->getStatus() == Passed ) { + // we have convergence + // convtest->whichVecs() tells us which vectors from lockvecs and solver state are the ones we want + // convtest->howMany() will tell us how many + break; + } + //////////////////////////////////////////////////////////////////////////////////// + // + // check for restarting before locking: if we need to lock, it will happen after the restart + // + //////////////////////////////////////////////////////////////////////////////////// + else if ( bd_solver->getCurSubspaceDim() == bd_solver->getMaxSubspaceDim() ) { + + if ( numRestarts >= maxRestarts_ ) { + break; // break from while(1){bd_solver->iterate()} + } + numRestarts++; + + printer->stream(IterationDetails) << " Performing restart number " << numRestarts << " of " << maxRestarts_ << std::endl << std::endl; + + BlockDavidsonState state = bd_solver->getState(); + int curdim = state.curDim; + int newdim = numRestartBlocks_*blockSize_; + + // + // compute eigenvectors of the projected problem + Teuchos::SerialDenseMatrix S(curdim,curdim); + std::vector theta(curdim); + int rank = curdim; + int info = msutils::directSolver(curdim,*state.KK,Teuchos::null,S,theta,rank,10); + TEST_FOR_EXCEPTION(info != 0 ,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): error calling SolverUtils::directSolver."); // this should never happen + TEST_FOR_EXCEPTION(rank != curdim,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): direct solve did not compute all eigenvectors."); // this should never happen + + // + // sort the eigenvalues (so that we can order the eigenvectors) + { + std::vector order(curdim); + sorter->sort(bd_solver.get(),curdim,theta,&order); + // + // apply the same ordering to the primitive ritz vectors + msutils::permuteVectors(order,S); + } + // + // select the significant primitive ritz vectors + Teuchos::SerialDenseMatrix Sr(Teuchos::View,S,curdim,newdim); + // + // generate newKK = Sr'*KKold*Sr + Teuchos::SerialDenseMatrix newKK(newdim,newdim); + { + Teuchos::SerialDenseMatrix KKtmp(curdim,newdim), + KKold(Teuchos::View,*state.KK,curdim,curdim); + int teuchosRet; + // KKtmp = KKold*Sr + teuchosRet = KKtmp.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,KKold,Sr,ZERO); + TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply."); + // newKK = Sr'*KKtmp = Sr'*KKold*Sr + teuchosRet = newKK.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,Sr,KKtmp,ZERO); + TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply."); + // make it Hermitian in memory + for (int j=0; j rstate; + rstate.curDim = newdim; + rstate.KK = Teuchos::rcp( &newKK, false ); + // + // we know that newX = newV*Sr(:,1:bS) = oldV*S(:1:bS) = oldX + // the restarting preserves the Ritz vectors and residual + // for the Ritz values, we want all of the values associated with newV. + // these have already been placed at the beginning of theta + rstate.X = state.X; + rstate.KX = state.KX; + rstate.MX = state.MX; + rstate.R = state.R; + rstate.T = Teuchos::rcp( new std::vector(&theta[0],&theta[newdim]) ); + + if (inSituRestart_ == true) { + // + // get non-const pointer to solver's basis so we can work in situ + Teuchos::RCP solverbasis = Teuchos::rcp_const_cast(state.V); + // + // perform Householder QR of Sr = Q [D;0], where D is unit diag. + // WARNING: this will overwrite Sr; however, we do not need Sr anymore after this + std::vector tau(newdim), work(newdim); + int info; + lapack.GEQRF(curdim,newdim,Sr.values(),Sr.stride(),&tau[0],&work[0],work.size(),&info); + TEST_FOR_EXCEPTION(info != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): error calling GEQRF during restarting."); + if (printer->isVerbosity(Debug)) { + Teuchos::SerialDenseMatrix R(Teuchos::Copy,Sr,newdim,newdim); + for (int j=0; jstream(Debug) << "||Triangular factor of Sr - I||: " << R.normFrobenius() << std::endl; + } + // + // perform implicit oldV*Sr + // this actually performs oldV*[Sr Su*M] = [newV truncV], for some unitary M + // we are actually interested in only the first newdim vectors of the result + { + std::vector curind(curdim); + for (int i=0; i oldV = MVT::CloneView(*solverbasis,curind); + msutils::applyHouse(newdim,*oldV,Sr,tau,workMV); + } + // + // put the new basis into the state for initialize() + // the new basis is contained in the the first newdim columns of solverbasis + // initialize() will recognize that pointer bd_solver.V_ == pointer rstate.V, and will neglect the copy. + rstate.V = solverbasis; + } + else { // inSituRestart == false) + // newV = oldV*Sr, explicitly. workspace is in workMV + std::vector curind(curdim), newind(newdim); + for (int i=0; i oldV = MVT::CloneView(*state.V,curind); + Teuchos::RCP newV = MVT::CloneView(*workMV ,newind); + + MVT::MvTimesMatAddMv(ONE,*oldV,Sr,ZERO,*newV); + // + // put the new basis into the state for initialize() + rstate.V = newV; + } + + // + // send the new state to the solver + bd_solver->initialize(rstate); + } // end of restarting + //////////////////////////////////////////////////////////////////////////////////// + // + // check locking if we didn't converge or restart + // + //////////////////////////////////////////////////////////////////////////////////// + else if (locktest != Teuchos::null && locktest->getStatus() == Passed) { + + // + // get current state + BlockDavidsonState state = bd_solver->getState(); + const int curdim = state.curDim; + + // + // get number,indices of vectors to be locked + TEST_FOR_EXCEPTION(locktest->howMany() <= 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): status test mistake."); + TEST_FOR_EXCEPTION(locktest->howMany() != (int)locktest->whichVecs().size(),std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): status test mistake."); + // + // don't lock more than maxLocked_; we didn't allocate enough space. + std::vector tmp_vector_int; + if (curNumLocked + locktest->howMany() > maxLocked_) { + // just use the first of them + tmp_vector_int.insert(tmp_vector_int.begin(),locktest->whichVecs().begin(),locktest->whichVecs().begin()+maxLocked_-curNumLocked); + } + else { + tmp_vector_int = locktest->whichVecs(); + } + const std::vector lockind(tmp_vector_int); + const int numNewLocked = lockind.size(); + // + // generate indices of vectors left unlocked + // curind = [0,...,curdim-1] = UNION( lockind, unlockind ) + const int numUnlocked = curdim-numNewLocked; + tmp_vector_int.resize(curdim); + for (int i=0; i curind(tmp_vector_int); // curind = [0 ... curdim-1] + tmp_vector_int.resize(numUnlocked); + set_difference(curind.begin(),curind.end(),lockind.begin(),lockind.end(),tmp_vector_int.begin()); + const std::vector unlockind(tmp_vector_int); // unlockind = [0 ... curdim-1] - lockind + tmp_vector_int.clear(); + + // + // debug printing + if (printer->isVerbosity(Debug)) { + printer->print(Debug,"Locking vectors: "); + for (unsigned int i=0; istream(Debug) << " " << lockind[i];} + printer->print(Debug,"\n"); + } + + // + // we need primitive ritz vectors/values: + // [S,L] = eig(oldKK) + // + // this will be partitioned as follows: + // locked: Sl = S(lockind) // we won't actually need Sl + // unlocked: Su = S(unlockind) + // + Teuchos::SerialDenseMatrix S(curdim,curdim); + std::vector theta(curdim); + { + int rank = curdim; + int info = msutils::directSolver(curdim,*state.KK,Teuchos::null,S,theta,rank,10); + TEST_FOR_EXCEPTION(info != 0 ,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): error calling SolverUtils::directSolver."); // this should never happen + TEST_FOR_EXCEPTION(rank != curdim,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): direct solve did not compute all eigenvectors."); // this should never happen + // + // sort the eigenvalues (so that we can order the eigenvectors) + std::vector order(curdim); + sorter->sort(bd_solver.get(),curdim,theta,&order); + // + // apply the same ordering to the primitive ritz vectors + msutils::permuteVectors(order,S); + } + // + // select the unlocked ritz vectors + // the indexing in unlockind is relative to the ordered primitive ritz vectors + // (this is why we ordered theta,S above) + Teuchos::SerialDenseMatrix Su(curdim,numUnlocked); + for (int i=0; i defV, augV; + if (inSituRestart_ == true) { + // + // get non-const pointer to solver's basis so we can work in situ + Teuchos::RCP solverbasis = Teuchos::rcp_const_cast(state.V); + // + // perform Householder QR of Su = Q [D;0], where D is unit diag. + // work on a copy of Su, since we need Su below to build newKK + Teuchos::SerialDenseMatrix copySu(Su); + std::vector tau(numUnlocked), work(numUnlocked); + int info; + lapack.GEQRF(curdim,numUnlocked,copySu.values(),copySu.stride(),&tau[0],&work[0],work.size(),&info); + TEST_FOR_EXCEPTION(info != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): error calling GEQRF during restarting."); + if (printer->isVerbosity(Debug)) { + Teuchos::SerialDenseMatrix R(Teuchos::Copy,copySu,numUnlocked,numUnlocked); + for (int j=0; jstream(Debug) << "||Triangular factor of Su - I||: " << R.normFrobenius() << std::endl; + } + // + // perform implicit oldV*Su + // this actually performs oldV*[Su Sl*M] = [defV lockV], for some unitary M + // we are actually interested in only the first numUnlocked vectors of the result + { + Teuchos::RCP oldV = MVT::CloneView(*solverbasis,curind); + msutils::applyHouse(numUnlocked,*oldV,copySu,tau,workMV); + } + std::vector defind(numUnlocked), augind(numNewLocked); + for (int i=0; i defind(numUnlocked), augind(numNewLocked); + for (int i=0; i oldV = MVT::CloneView(*state.V,curind); + defV = MVT::CloneView(*workMV,defind); + augV = MVT::CloneView(*workMV,augind); + + MVT::MvTimesMatAddMv(ONE,*oldV,Su,ZERO,*defV); + } + + // + // lockvecs will be partitioned as follows: + // lockvecs = [curlocked augTmp ...] + // - augTmp will be used for the storage of M*augV and K*augV + // later, the locked vectors (stored in state.X and referenced via const MV view newLocked) + // will be moved into lockvecs on top of augTmp when it is no longer needed as workspace. + // - curlocked will be used in orthogonalization of augV + // + // newL is the new locked vectors; newL = oldV*Sl = RitzVectors(lockind) + // we will not produce them, but instead retrieve them from RitzVectors + // + Teuchos::RCP curlocked, newLocked; + Teuchos::RCP augTmp; + { + // setup curlocked + if (curNumLocked > 0) { + std::vector curlockind(curNumLocked); + for (int i=0; i augtmpind(numNewLocked); + for (int i=0; igetRitzVectors(),lockind); + } + + // + // generate augV and perform orthogonalization + // + MVT::MvRandom(*augV); + // + // orthogonalize it against auxvecs, defV, and all locked vectors (new and current) + // use augTmp as storage for M*augV, if hasM + { + Teuchos::Array > against; + Teuchos::Array > > dummy; + if (probauxvecs != Teuchos::null) against.push_back(probauxvecs); + if (curlocked != Teuchos::null) against.push_back(curlocked); + against.push_back(newLocked); + against.push_back(defV); + if (problem_->getM() != Teuchos::null) { + OPT::Apply(*problem_->getM(),*augV,*augTmp); + } + ortho->projectAndNormalizeMat(*augV,augTmp,dummy,Teuchos::null,against); + } + + // + // form newKK + // + // newKK = newV'*K*newV = [Su'*KK*Su defV'*K*augV] + // [augV'*K*defV augV'*K*augV] + // + // first, generate the principal submatrix, the projection of K onto the unlocked portion of oldV + // + Teuchos::SerialDenseMatrix newKK(curdim,curdim); + { + Teuchos::SerialDenseMatrix KKtmp(curdim,numUnlocked), + KKold(Teuchos::View,*state.KK,curdim,curdim), + KK11(Teuchos::View,newKK,numUnlocked,numUnlocked); + int teuchosRet; + // KKtmp = KKold*Su + teuchosRet = KKtmp.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,KKold,Su,ZERO); + TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply."); + // KK11 = Su'*KKtmp = Su'*KKold*Su + teuchosRet = KK11.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,Su,KKtmp,ZERO); + TEST_FOR_EXCEPTION(teuchosRet != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): Logic error calling SerialDenseMatrix::multiply."); + } + // + // project the stiffness matrix on augV + { + OPT::Apply(*problem_->getOperator(),*augV,*augTmp); + Teuchos::SerialDenseMatrix KK12(Teuchos::View,newKK,numUnlocked,numNewLocked,0,numUnlocked), + KK22(Teuchos::View,newKK,numNewLocked,numNewLocked,numUnlocked,numUnlocked); + MVT::MvTransMv(ONE,*defV,*augTmp,KK12); + MVT::MvTransMv(ONE,*augV,*augTmp,KK22); + } + // + // done with defV,augV + defV = Teuchos::null; + augV = Teuchos::null; + // + // make it hermitian in memory (fill in KK21) + for (int j=0; j > allvals = bd_solver->getRitzValues(); + for (int i=0; i indlock(numNewLocked); + for (int i=0; i curlockind(curNumLocked); + for (int i=0; isetAuxVals(lockvals); + + Teuchos::Array< Teuchos::RCP > aux; + if (probauxvecs != Teuchos::null) aux.push_back(probauxvecs); + aux.push_back(curlocked); + bd_solver->setAuxVecs(aux); + + if (curNumLocked == maxLocked_) { + // disabled locking now by setting quorum to unreachable number + locktest->setQuorum(blockSize_+1); + } + } + + // + // prepare new state + BlockDavidsonState rstate; + rstate.curDim = curdim; + if (inSituRestart_) { + // data is already in the solver's memory + rstate.V = state.V; + } + else { + // data is in workspace and will be copied to solver memory + rstate.V = workMV; + } + rstate.KK = Teuchos::rcp( &newKK, false ); + // + // pass new state to the solver + bd_solver->initialize(rstate); + } // end of locking + //////////////////////////////////////////////////////////////////////////////////// + // + // we returned from iterate(), but none of our status tests Passed. + // something is wrong, and it is probably our fault. + // + //////////////////////////////////////////////////////////////////////////////////// + else { + TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): Invalid return from bd_solver::iterate()."); + } + } + catch (std::exception e) { + printer->stream(Errors) << "Error! Caught exception in BlockDavidson::iterate() at iteration " << bd_solver->getNumIters() << std::endl + << e.what() << std::endl; + throw; + } + } + + // clear temp space + workMV = Teuchos::null; + + sol.numVecs = convtest->howMany(); + if (sol.numVecs > 0) { + sol.Evecs = MVT::Clone(*problem_->getInitVec(),sol.numVecs); + sol.Espace = sol.Evecs; + sol.Evals.resize(sol.numVecs); + std::vector vals(sol.numVecs); + + // copy them into the solution + std::vector which = convtest->whichVecs(); + // indices between [0,blockSize) refer to vectors/values in the solver + // indices between [blockSize,blocksize+curNumLocked) refer to locked vectors/values + // everything has already been ordered by the solver; we just have to partition the two references + std::vector inlocked(0), insolver(0); + for (unsigned int i=0; i= curNumLocked+blockSize_,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): indexing mistake."); + inlocked.push_back(which[i] - blockSize_); + } + } + + TEST_FOR_EXCEPTION(insolver.size() + inlocked.size() != (unsigned int)sol.numVecs,std::logic_error,"Anasazi::BlockDavidsonSolMgr::solve(): indexing mistake."); + + // set the vecs,vals in the solution + if (insolver.size() > 0) { + // set vecs + int lclnum = insolver.size(); + std::vector tosol(lclnum); + for (int i=0; i v = MVT::CloneView(*bd_solver->getRitzVectors(),insolver); + MVT::SetBlock(*v,tosol,*sol.Evecs); + // set vals + std::vector > fromsolver = bd_solver->getRitzValues(); + for (unsigned int i=0; i 0) { + int solnum = insolver.size(); + // set vecs + int lclnum = inlocked.size(); + std::vector tosol(lclnum); + for (int i=0; i v = MVT::CloneView(*lockvecs,inlocked); + MVT::SetBlock(*v,tosol,*sol.Evecs); + // set vals + for (unsigned int i=0; i order(sol.numVecs); + sorter->sort(bd_solver.get(), sol.numVecs, vals, &order ); + // store the values in the Eigensolution + for (int i=0; icurrentStatus(printer->stream(FinalSummary)); + + // print timing information + Teuchos::TimeMonitor::summarize(printer->stream(TimingDetails)); + + problem_->setSolution(sol); + printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl; + + if (sol.numVecs < nev) { + return Unconverged; // return from BlockDavidsonSolMgr::solve() + } + return Converged; // return from BlockDavidsonSolMgr::solve() +} + + +} // end Anasazi namespace + +#endif /* ANASAZI_BLOCKDAVIDSON_SOLMGR_HPP */ diff --git a/fastlib/trilinos/include/AnasaziBlockKrylovSchur.hpp b/fastlib/trilinos/include/AnasaziBlockKrylovSchur.hpp new file mode 100644 index 0000000000..56d379a045 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziBlockKrylovSchur.hpp @@ -0,0 +1,1854 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziBlockKrylovSchur.hpp + \brief Implementation of a block Krylov-Schur eigensolver. +*/ + +#ifndef ANASAZI_BLOCK_KRYLOV_SCHUR_HPP +#define ANASAZI_BLOCK_KRYLOV_SCHUR_HPP + +#include "AnasaziTypes.hpp" + +#include "AnasaziEigensolver.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "Teuchos_ScalarTraits.hpp" + +#include "AnasaziOrthoManager.hpp" + +#include "Teuchos_LAPACK.hpp" +#include "Teuchos_BLAS.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" +#include "Teuchos_ParameterList.hpp" +#include "Teuchos_TimeMonitor.hpp" + +#ifdef HAVE_TEUCHOS_COMPLEX +#if defined(HAVE_COMPLEX) +#define ANSZI_CPLX_CLASS std::complex +#elif defined(HAVE_COMPLEX_H) +#define ANSZI_CPLX_CLASS ::complex +#endif +#endif + +/*! \class Anasazi::BlockKrylovSchur + + \brief This class implements the block Krylov-Schur iteration, + for solving linear eigenvalue problems. + + This method is a block version of the iteration presented by G.W. Stewart + in "A Krylov-Schur Algorithm for Large Eigenproblems", + SIAM J. Matrix Anal. Appl., Vol 23(2001), No. 3, pp. 601-614. + + \ingroup anasazi_solver_framework + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, Heidi Thornquist +*/ + +namespace Anasazi { + + //! @name BlockKrylovSchur Structures + //@{ + + /** \brief Structure to contain pointers to BlockKrylovSchur state variables. + * + * This struct is utilized by BlockKrylovSchur::initialize() and BlockKrylovSchur::getState(). + */ + template + struct BlockKrylovSchurState { + /*! \brief The current dimension of the reduction. + * + * This should always be equal to BlockKrylovSchur::getCurSubspaceDim() + */ + int curDim; + /*! \brief The current Krylov basis. */ + Teuchos::RCP V; + /*! \brief The current Hessenberg matrix. + * + * The \c curDim by \c curDim leading submatrix of H is the + * projection of problem->getOperator() by the first \c curDim vectors in V. + */ + Teuchos::RCP > H; + /*! \brief The current Schur form reduction of the valid part of H. */ + Teuchos::RCP > S; + /*! \brief The current Schur vectors of the valid part of H. */ + Teuchos::RCP > Q; + BlockKrylovSchurState() : curDim(0), V(Teuchos::null), + H(Teuchos::null), S(Teuchos::null), + Q(Teuchos::null) {} + }; + + //@} + + //! @name BlockKrylovSchur Exceptions + //@{ + + /** \brief BlockKrylovSchurInitFailure is thrown when the BlockKrylovSchur solver is unable to + * generate an initial iterate in the BlockKrylovSchur::initialize() routine. + * + * This exception is thrown from the BlockKrylovSchur::initialize() method, which is + * called by the user or from the BlockKrylovSchur::iterate() method if isInitialized() + * == \c false. + * + * In the case that this exception is thrown, + * BlockKrylovSchur::isInitialized() will be \c false and the user will need to provide + * a new initial iterate to the solver. + * + */ + class BlockKrylovSchurInitFailure : public AnasaziError {public: + BlockKrylovSchurInitFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + /** \brief BlockKrylovSchurOrthoFailure is thrown when the orthogonalization manager is + * unable to generate orthonormal columns from the new basis vectors. + * + * This exception is thrown from the BlockKrylovSchur::iterate() method. + * + */ + class BlockKrylovSchurOrthoFailure : public AnasaziError {public: + BlockKrylovSchurOrthoFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + //@} + + + template + class BlockKrylovSchur : public Eigensolver { + public: + //! @name Constructor/Destructor + //@{ + + /*! \brief %BlockKrylovSchur constructor with eigenproblem, solver utilities, and parameter list of solver options. + * + * This constructor takes pointers required by the eigensolver, in addition + * to a parameter list of options for the eigensolver. These options include the following: + * - "Block Size" - an \c int specifying the block size used by the algorithm. This can also be specified using the setBlockSize() method. Default: 1 + * - "Num Blocks" - an \c int specifying the maximum number of blocks allocated for the solver basis. Default: 3*problem->getNEV() + * - "Step Size" - an \c int specifying how many iterations are performed between computations of eigenvalues and eigenvectors.\n + * Note: This parameter is mandatory. + * - "Number of Ritz Vectors" - an \c int specifying how many Ritz vectors are computed on calls to getRitzVectors(). Default: 0 + * - "Print Number of Ritz Values" - an \c int specifying how many Ritz values are printed on calls to currentStatus(). Default: "Block Size" + */ + BlockKrylovSchur( const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms + ); + + //! %BlockKrylovSchur destructor. + virtual ~BlockKrylovSchur() {}; + //@} + + + //! @name Solver methods + //@{ + + /*! \brief This method performs Block Krylov-Schur iterations until the status + * test indicates the need to stop or an error occurs (in which case, an + * exception is thrown). + * + * iterate() will first determine whether the solver is inintialized; if + * not, it will call initialize() using default arguments. After + * initialization, the solver performs Block Krylov-Schur iterations until the + * status test evaluates as ::Passed, at which point the method returns to + * the caller. + * + * The Block Krylov-Schur iteration proceeds as follows: + * -# The operator problem->getOperator() is applied to the newest \c blockSize vectors in the Krylov basis. + * -# The resulting vectors are orthogonalized against the auxiliary vectors and the previous basis vectors, and made orthonormal. + * -# The Hessenberg matrix is updated. + * -# If we have performed \c stepSize iterations since the last update, update the Ritz values and Ritz residuals. + * + * The status test is queried at the beginning of the iteration. + * + * Possible exceptions thrown include the BlockKrylovSchurOrthoFailure. + * + */ + void iterate(); + + /*! \brief Initialize the solver to an iterate, providing a Krylov basis and Hessenberg matrix. + * + * The %BlockKrylovSchur eigensolver contains a certain amount of state, + * consisting of the current Krylov basis and the associated Hessenberg matrix. + * + * initialize() gives the user the opportunity to manually set these, + * although this must be done with caution, abiding by the rules given + * below. All notions of orthogonality and orthonormality are derived from + * the inner product specified by the orthogonalization manager. + * + * \post + *
  • isInitialized() == \c true (see post-conditions of isInitialize()) + * + * The user has the option of specifying any component of the state using + * initialize(). However, these arguments are assumed to match the + * post-conditions specified under isInitialized(). Any necessary component of the + * state not given to initialize() will be generated. + * + * Note, for any pointer in \c newstate which directly points to the multivectors in + * the solver, the data is not copied. + */ + void initialize(BlockKrylovSchurState state); + + /*! \brief Initialize the solver with the initial vectors from the eigenproblem + * or random data. + */ + void initialize(); + + /*! \brief Indicates whether the solver has been initialized or not. + * + * \return bool indicating the state of the solver. + * \post + * If isInitialized() == \c true: + * - the first getCurSubspaceDim() vectors of V are orthogonal to auxiliary vectors and have orthonormal columns + * - the principal Hessenberg submatrix of of H contains the Hessenberg matrix associated with V + */ + bool isInitialized() const { return initialized_; } + + /*! \brief Get the current state of the eigensolver. + * + * The data is only valid if isInitialized() == \c true. + * + * \returns A BlockKrylovSchurState object containing const pointers to the current + * solver state. + */ + BlockKrylovSchurState getState() const { + BlockKrylovSchurState state; + state.curDim = curDim_; + state.V = V_; + state.H = H_; + state.Q = Q_; + state.S = schurH_; + return state; + } + + //@} + + + //! @name Status methods + //@{ + + //! \brief Get the current iteration count. + int getNumIters() const { return(iter_); } + + //! \brief Reset the iteration count. + void resetNumIters() { iter_=0; } + + /*! \brief Get the Ritz vectors. + * + * \return A multivector of columns not exceeding the maximum dimension of the subspace + * containing the Ritz vectors from the most recent call to computeRitzVectors(). + * + * \note To see if the returned Ritz vectors are current, call isRitzVecsCurrent(). + */ + Teuchos::RCP getRitzVectors() { return ritzVectors_; } + + /*! \brief Get the Ritz values. + * + * \return A vector of length not exceeding the maximum dimension of the subspace + * containing the Ritz values from the most recent Schur form update. + * + * \note To see if the returned Ritz values are current, call isRitzValsCurrent(). + */ + std::vector > getRitzValues() { + std::vector > ret = ritzValues_; + ret.resize(ritzIndex_.size()); + return ret; + } + + /*! \brief Get the Ritz index vector. + * + * \return A vector of length not exceeding the maximum dimension of the subspace + * containing the index vector for the Ritz values and Ritz vectors, if they are computed. + */ + std::vector getRitzIndex() { return ritzIndex_; } + + /*! \brief Get the current residual norms. + * + * \note Block Krylov-Schur cannot provide this so a zero length vector will be returned. + */ + std::vector::magnitudeType> getResNorms() { + std::vector::magnitudeType> ret(0); + return ret; + } + + /*! \brief Get the current residual 2-norms + * + * \note Block Krylov-Schur cannot provide this so a zero length vector will be returned. + */ + std::vector::magnitudeType> getRes2Norms() { + std::vector::magnitudeType> ret(0); + return ret; + } + + /*! \brief Get the current Ritz residual 2-norms + * + * \return A vector of length blockSize containing the 2-norms of the Ritz residuals. + */ + std::vector::magnitudeType> getRitzRes2Norms() { + std::vector::magnitudeType> ret = ritzResiduals_; + ret.resize(ritzIndex_.size()); + return ret; + } + + //@} + + //! @name Accessor routines + //@{ + + //! Get a constant reference to the eigenvalue problem. + const Eigenproblem& getProblem() const { return(*problem_); }; + + /*! \brief Set the blocksize and number of blocks to be used by the + * iterative solver in solving this eigenproblem. + * + * Changing either the block size or the number of blocks will reset the + * solver to an uninitialized state. + */ + void setSize(int blockSize, int numBlocks); + + //! \brief Set the blocksize. + void setBlockSize(int blockSize); + + //! \brief Set the step size. + void setStepSize(int stepSize); + + //! \brief Set the number of Ritz vectors to compute. + void setNumRitzVectors(int numRitzVecs); + + //! \brief Get the step size. + int getStepSize() const { return(stepSize_); } + + //! Get the blocksize to be used by the iterative solver in solving this eigenproblem. + int getBlockSize() const { return(blockSize_); } + + //! \brief Get the number of Ritz vectors to compute. + int getNumRitzVectors() const { return(numRitzVecs_); } + + /*! \brief Get the dimension of the search subspace used to generate the current eigenvectors and eigenvalues. + * + * \return An integer specifying the rank of the Krylov subspace currently in use by the eigensolver. If isInitialized() == \c false, + * the return is 0. + */ + int getCurSubspaceDim() const { + if (!initialized_) return 0; + return curDim_; + } + + //! Get the maximum dimension allocated for the search subspace. + int getMaxSubspaceDim() const { return (problem_->isHermitian()?blockSize_*numBlocks_:blockSize_*numBlocks_+1); } + + + /*! \brief Set the auxiliary vectors for the solver. + * + * Because the current Krylov subspace cannot be assumed + * orthogonal to the new auxiliary vectors, a call to setAuxVecs() will + * reset the solver to the uninitialized state. This happens only in the + * case where the new auxiliary vectors have a combined dimension of + * greater than zero. + * + * In order to preserve the current state, the user will need to extract + * it from the solver using getState(), orthogonalize it against the + * new auxiliary vectors, and reinitialize using initialize(). + */ + void setAuxVecs(const Teuchos::Array > &auxvecs); + + //! Get the auxiliary vectors for the solver. + Teuchos::Array > getAuxVecs() const {return auxVecs_;} + + //@} + + //! @name Output methods + //@{ + + //! This method requests that the solver print out its current status to screen. + void currentStatus(std::ostream &os); + + //@} + + //! @name Block-Krylov Schur status routines + //@{ + + //! Get the status of the Ritz vectors currently stored in the eigensolver. + bool isRitzVecsCurrent() const { return ritzVecsCurrent_; } + + //! Get the status of the Ritz values currently stored in the eigensolver. + bool isRitzValsCurrent() const { return ritzValsCurrent_; } + + //! Get the status of the Schur form currently stored in the eigensolver. + bool isSchurCurrent() const { return schurCurrent_; } + + //@} + + //! @name Block-Krylov Schur compute routines + //@{ + + //! Compute the Ritz vectors using the current Krylov factorization. + void computeRitzVectors(); + + //! Compute the Ritz values using the current Krylov factorization. + void computeRitzValues(); + + //! Compute the Schur form of the projected eigenproblem from the current Krylov factorization. + void computeSchurForm( const bool sort = true ); + + //@} + + private: + // + // Convenience typedefs + // + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + typedef Teuchos::ScalarTraits SCT; + typedef typename SCT::magnitudeType MagnitudeType; + typedef typename std::vector::iterator STiter; + typedef typename std::vector::iterator MTiter; + const MagnitudeType MT_ONE; + const MagnitudeType MT_ZERO; + const MagnitudeType NANVAL; + const ScalarType ST_ONE; + const ScalarType ST_ZERO; + // + // Internal structs + // + struct CheckList { + bool checkV; + bool checkArn; + bool checkAux; + CheckList() : checkV(false), checkArn(false), checkAux(false) {}; + }; + // + // Internal methods + // + std::string accuracyCheck(const CheckList &chk, const std::string &where) const; + void sortSchurForm( Teuchos::SerialDenseMatrix& H, + Teuchos::SerialDenseMatrix& Q, + std::vector& order ); + // + // Classes inputed through constructor that define the eigenproblem to be solved. + // + const Teuchos::RCP > problem_; + const Teuchos::RCP > sm_; + const Teuchos::RCP > om_; + const Teuchos::RCP > tester_; + const Teuchos::RCP > orthman_; + // + // Information obtained from the eigenproblem + // + Teuchos::RCP Op_; + // + // Internal timers + // + Teuchos::RCP timerOp_, timerSortRitzVal_, + timerCompSF_, timerSortSF_, + timerCompRitzVec_, timerOrtho_; + // + // Counters + // + int count_ApplyOp_; + + // + // Algorithmic parameters. + // + // blockSize_ is the solver block size; it controls the number of eigenvectors that + // we compute, the number of residual vectors that we compute, and therefore the number + // of vectors added to the basis on each iteration. + int blockSize_; + // numBlocks_ is the size of the allocated space for the Krylov basis, in blocks. + int numBlocks_; + // stepSize_ dictates how many iterations are performed before eigenvectors and eigenvalues + // are computed again + int stepSize_; + + // + // Current solver state + // + // initialized_ specifies that the basis vectors have been initialized and the iterate() routine + // is capable of running; _initialize is controlled by the initialize() member method + // For the implications of the state of initialized_, please see documentation for initialize() + bool initialized_; + // + // curDim_ reflects how much of the current basis is valid + // NOTE: for Hermitian, 0 <= curDim_ <= blockSize_*numBlocks_ + // for non-Hermitian, 0 <= curDim_ <= blockSize_*numBlocks_ + 1 + // this also tells us how many of the values in _theta are valid Ritz values + int curDim_; + // + // State Multivecs + Teuchos::RCP ritzVectors_, V_; + int numRitzVecs_; + // + // Projected matrices + // H_ : Projected matrix from the Krylov-Schur factorization AV = VH + FB^T + // + Teuchos::RCP > H_; + // + // Schur form of Projected matrices (these are only updated when the Ritz values/vectors are updated). + // schurH_: Schur form reduction of H + // Q_: Schur vectors of H + Teuchos::RCP > schurH_; + Teuchos::RCP > Q_; + // + // Auxiliary vectors + Teuchos::Array > auxVecs_; + int numAuxVecs_; + // + // Number of iterations that have been performed. + int iter_; + // + // State flags + bool ritzVecsCurrent_, ritzValsCurrent_, schurCurrent_; + // + // Current eigenvalues, residual norms + std::vector > ritzValues_; + std::vector ritzResiduals_; + // + // Current index vector for Ritz values and vectors + std::vector ritzIndex_; // computed by BKS + std::vector ritzOrder_; // returned from sort manager + // + // Number of Ritz pairs to be printed upon output, if possible + int numRitzPrint_; + }; + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Helper function for correctly storing the Ritz values when the eigenproblem is non-Hermitian + // This allows us to use template specialization to compute the right index vector and correctly + // handle complex-conjugate pairs. + template + void sortRitzValues( const std::vector::magnitudeType>& rRV, + const std::vector::magnitudeType>& iRV, + std::vector >* RV, std::vector* RO, std::vector* RI ) + { + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + MagnitudeType MT_ZERO = Teuchos::ScalarTraits::zero(); + + int curDim = (int)rRV.size(); + int i = 0; + + // Clear the current index. + RI->clear(); + + // Place the Ritz values from rRV and iRV into the RV container. + while( i < curDim ) { + if ( iRV[i] != MT_ZERO ) { + // + // We will have this situation for real-valued, non-Hermitian matrices. + (*RV)[i].set(rRV[i], iRV[i]); + (*RV)[i+1].set(rRV[i+1], iRV[i+1]); + + // Make sure that complex conjugate pairs have their positive imaginary part first. + if ( (*RV)[i].imagpart < MT_ZERO ) { + // The negative imaginary part is first, so swap the order of the ritzValues and ritzOrders. + Anasazi::Value tmp_ritz( (*RV)[i] ); + (*RV)[i] = (*RV)[i+1]; + (*RV)[i+1] = tmp_ritz; + + int tmp_order = (*RO)[i]; + (*RO)[i] = (*RO)[i+1]; + (*RO)[i+1] = tmp_order; + + } + RI->push_back(1); RI->push_back(-1); + i = i+2; + } else { + // + // The Ritz value is not complex. + (*RV)[i].set(rRV[i], MT_ZERO); + RI->push_back(0); + i++; + } + } + } + +#ifdef HAVE_TEUCHOS_COMPLEX + // Template specialization for the complex scalar type. + void sortRitzValues( const std::vector& rRV, + const std::vector& iRV, + std::vector > >* RV, + std::vector* RO, std::vector* RI ) + { + int curDim = (int)rRV.size(); + int i = 0; + + // Clear the current index. + RI->clear(); + + // Place the Ritz values from rRV and iRV into the RV container. + while( i < curDim ) { + (*RV)[i].set(rRV[i], iRV[i]); + RI->push_back(0); + i++; + } + } +#endif + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Helper function for correctly scaling the eigenvectors of the projected eigenproblem. + // This allows us to use template specialization to compute the right scaling so the + // Ritz residuals are correct. + template + void scaleRitzVectors( const std::vector::magnitudeType>& iRV, + Teuchos::SerialDenseMatrix* S ) + { + ScalarType ST_ONE = Teuchos::ScalarTraits::one(); + + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + MagnitudeType MT_ZERO = Teuchos::ScalarTraits::zero(); + + Teuchos::LAPACK lapack_mag; + Teuchos::BLAS blas; + + int i = 0, curDim = S->numRows(); + ScalarType temp; + ScalarType* s_ptr = S->values(); + while( i < curDim ) { + if ( iRV[i] != MT_ZERO ) { + temp = lapack_mag.LAPY2( blas.NRM2( curDim, s_ptr+i*curDim, 1 ), + blas.NRM2( curDim, s_ptr+(i+1)*curDim, 1 ) ); + blas.SCAL( curDim, ST_ONE/temp, s_ptr+i*curDim, 1 ); + blas.SCAL( curDim, ST_ONE/temp, s_ptr+(i+1)*curDim, 1 ); + i = i+2; + } else { + temp = blas.NRM2( curDim, s_ptr+i*curDim, 1 ); + blas.SCAL( curDim, ST_ONE/temp, s_ptr+i*curDim, 1 ); + i++; + } + } + } + +#ifdef HAVE_TEUCHOS_COMPLEX + // Template specialization for the complex scalar type. + void scaleRitzVectors( const std::vector& iRV, + Teuchos::SerialDenseMatrix >* S ) + { + typedef ANSZI_CPLX_CLASS ST; + ST ST_ONE = Teuchos::ScalarTraits::one(); + + Teuchos::BLAS blas; + + int i = 0, curDim = S->numRows(); + ST temp; + ST* s_ptr = S->values(); + while( i < curDim ) { + temp = blas.NRM2( curDim, s_ptr+i*curDim, 1 ); + blas.SCAL( curDim, ST_ONE/temp, s_ptr+i*curDim, 1 ); + i++; + } + } +#endif + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Helper function for correctly computing the Ritz residuals of the projected eigenproblem. + // This allows us to use template specialization to ensure the Ritz residuals are correct. + template + void computeRitzResiduals( const std::vector::magnitudeType>& iRV, + const Teuchos::SerialDenseMatrix& S, + std::vector::magnitudeType>* RR + ) + { + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + MagnitudeType MT_ZERO = Teuchos::ScalarTraits::zero(); + + Teuchos::LAPACK lapack_mag; + Teuchos::BLAS blas; + + int i = 0; + int s_stride = S.stride(); + int s_rows = S.numRows(); + int s_cols = S.numCols(); + ScalarType* s_ptr = S.values(); + + while( i < s_cols ) { + if ( iRV[i] != MT_ZERO ) { + (*RR)[i] = lapack_mag.LAPY2( blas.NRM2(s_rows, s_ptr + i*s_stride, 1), + blas.NRM2(s_rows, s_ptr + (i+1)*s_stride, 1) ); + (*RR)[i+1] = (*RR)[i]; + i = i+2; + } else { + (*RR)[i] = blas.NRM2(s_rows, s_ptr + i*s_stride, 1); + i++; + } + } + } + +#ifdef HAVE_TEUCHOS_COMPLEX + // Template specialization for the complex scalar type. + void computeRitzResiduals( const std::vector& iRV, + const Teuchos::SerialDenseMatrix >& S, + std::vector* RR + ) + { + Teuchos::BLAS > blas; + + int s_stride = S.stride(); + int s_rows = S.numRows(); + int s_cols = S.numCols(); + ANSZI_CPLX_CLASS* s_ptr = S.values(); + + for (int i=0; i + BlockKrylovSchur::BlockKrylovSchur( + const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms + ) : + MT_ONE(Teuchos::ScalarTraits::one()), + MT_ZERO(Teuchos::ScalarTraits::zero()), + NANVAL(Teuchos::ScalarTraits::nan()), + ST_ONE(Teuchos::ScalarTraits::one()), + ST_ZERO(Teuchos::ScalarTraits::zero()), + // problem, tools + problem_(problem), + sm_(sorter), + om_(printer), + tester_(tester), + orthman_(ortho), + // timers, counters + timerOp_(Teuchos::TimeMonitor::getNewTimer("Operation Op*x")), + timerSortRitzVal_(Teuchos::TimeMonitor::getNewTimer("Sorting Ritz values")), + timerCompSF_(Teuchos::TimeMonitor::getNewTimer("Computing Schur form")), + timerSortSF_(Teuchos::TimeMonitor::getNewTimer("Sorting Schur form")), + timerCompRitzVec_(Teuchos::TimeMonitor::getNewTimer("Computing Ritz vectors")), + timerOrtho_(Teuchos::TimeMonitor::getNewTimer("Orthogonalization")), + count_ApplyOp_(0), + // internal data + blockSize_(0), + numBlocks_(0), + stepSize_(0), + initialized_(false), + curDim_(0), + numRitzVecs_(0), + auxVecs_( Teuchos::Array >(0) ), + numAuxVecs_(0), + iter_(0), + ritzVecsCurrent_(false), + ritzValsCurrent_(false), + schurCurrent_(false), + numRitzPrint_(0) + { + TEST_FOR_EXCEPTION(problem_ == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: user specified null problem pointer."); + TEST_FOR_EXCEPTION(problem_->isProblemSet() == false, std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: user specified problem is not set."); + TEST_FOR_EXCEPTION(sorter == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: user specified null sort manager pointer."); + TEST_FOR_EXCEPTION(printer == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: user specified null output manager pointer."); + TEST_FOR_EXCEPTION(tester == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: user specified null status test pointer."); + TEST_FOR_EXCEPTION(ortho == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: user specified null ortho manager pointer."); + + // Get problem operator + Op_ = problem_->getOperator(); + + // get the step size + TEST_FOR_EXCEPTION(!params.isParameter("Step Size"), std::invalid_argument, + "Anasazi::BlockKrylovSchur::constructor: mandatory parameter 'Step Size' is not specified."); + int ss = params.get("Step Size",numBlocks_); + setStepSize(ss); + + // set the block size and allocate data + int bs = params.get("Block Size", 1); + int nb = params.get("Num Blocks", 3*problem_->getNEV()); + setSize(bs,nb); + + // get the number of Ritz vectors to compute and allocate data. + // --> if this parameter is not specified in the parameter list, then it's assumed that no Ritz vectors will be computed. + int numRitzVecs = params.get("Number of Ritz Vectors", 0); + setNumRitzVectors( numRitzVecs ); + + // get the number of Ritz values to print out when currentStatus is called. + numRitzPrint_ = params.get("Print Number of Ritz Values", bs); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the block size + // This simply calls setSize(), modifying the block size while retaining the number of blocks. + template + void BlockKrylovSchur::setBlockSize (int blockSize) + { + setSize(blockSize,numBlocks_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the step size. + template + void BlockKrylovSchur::setStepSize (int stepSize) + { + TEST_FOR_EXCEPTION(stepSize <= 0, std::invalid_argument, "Anasazi::BlockKrylovSchur::setStepSize(): new step size must be positive and non-zero."); + stepSize_ = stepSize; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the number of Ritz vectors to compute. + template + void BlockKrylovSchur::setNumRitzVectors (int numRitzVecs) + { + // This routine only allocates space; it doesn't not perform any computation + // any change in size will invalidate the state of the solver. + + TEST_FOR_EXCEPTION(numRitzVecs < 0, std::invalid_argument, "Anasazi::BlockKrylovSchur::setNumRitzVectors(): number of Ritz vectors to compute must be positive."); + + // Check to see if the number of requested Ritz vectors has changed. + if (numRitzVecs != numRitzVecs_) { + if (numRitzVecs) { + ritzVectors_ = Teuchos::null; + ritzVectors_ = MVT::Clone(*V_, numRitzVecs); + } else { + ritzVectors_ = Teuchos::null; + } + numRitzVecs_ = numRitzVecs; + ritzVecsCurrent_ = false; + } + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the block size and make necessary adjustments. + template + void BlockKrylovSchur::setSize (int blockSize, int numBlocks) + { + // This routine only allocates space; it doesn't not perform any computation + // any change in size will invalidate the state of the solver. + + TEST_FOR_EXCEPTION(numBlocks <= 0 || blockSize <= 0, std::invalid_argument, "Anasazi::BlockKrylovSchur::setSize was passed a non-positive argument."); + TEST_FOR_EXCEPTION(numBlocks < 3, std::invalid_argument, "Anasazi::BlockKrylovSchur::setSize(): numBlocks must be at least three."); + if (blockSize == blockSize_ && numBlocks == numBlocks_) { + // do nothing + return; + } + + blockSize_ = blockSize; + numBlocks_ = numBlocks; + + Teuchos::RCP tmp; + // grab some Multivector to Clone + // in practice, getInitVec() should always provide this, but it is possible to use a + // Eigenproblem with nothing in getInitVec() by manually initializing with initialize(); + // in case of that strange scenario, we will try to Clone from V_; first resort to getInitVec(), + // because we would like to clear the storage associated with V_ so we have room for the new V_ + if (problem_->getInitVec() != Teuchos::null) { + tmp = problem_->getInitVec(); + } + else { + tmp = V_; + TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::setSize(): eigenproblem did not specify initial vectors to clone from."); + } + + + ////////////////////////////////// + // blockSize*numBlocks dependent + // + int newsd; + if (problem_->isHermitian()) { + newsd = blockSize_*numBlocks_; + } else { + newsd = blockSize_*numBlocks_+1; + } + // check that new size is valid + TEST_FOR_EXCEPTION(newsd > MVT::GetVecLength(*tmp),std::invalid_argument, + "Anasazi::BlockKrylovSchur::setSize(): maximum basis size is larger than problem dimension."); + + ritzValues_.resize(newsd); + ritzResiduals_.resize(newsd,MT_ONE); + ritzOrder_.resize(newsd); + V_ = Teuchos::null; + V_ = MVT::Clone(*tmp,newsd+blockSize_); + H_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix(newsd+blockSize_,newsd) ); + Q_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix(newsd,newsd) ); + + initialized_ = false; + curDim_ = 0; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the auxiliary vectors + template + void BlockKrylovSchur::setAuxVecs(const Teuchos::Array > &auxvecs) { + typedef typename Teuchos::Array >::iterator tarcpmv; + + // set new auxiliary vectors + auxVecs_ = auxvecs; + + if (om_->isVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkAux = true; + om_->print( Debug, accuracyCheck(chk, ": in setAuxVecs()") ); + } + + numAuxVecs_ = 0; + for (tarcpmv i=auxVecs_.begin(); i != auxVecs_.end(); i++) { + numAuxVecs_ += MVT::GetNumberVecs(**i); + } + + // If the solver has been initialized, X and P are not necessarily orthogonal to new auxiliary vectors + if (numAuxVecs_ > 0 && initialized_) { + initialized_ = false; + } + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + /* Initialize the state of the solver + * + * POST-CONDITIONS: + * + * V_ is orthonormal, orthogonal to auxVecs_, for first curDim_ vectors + * + */ + + template + void BlockKrylovSchur::initialize(BlockKrylovSchurState newstate) + { + // NOTE: memory has been allocated by setBlockSize(). Use SetBlock below; do not Clone + + std::vector bsind(blockSize_); + for (int i=0; i getMaxSubspaceDim(), + std::invalid_argument, errstr ); + } + TEST_FOR_EXCEPTION( newstate.curDim > getMaxSubspaceDim(), + std::invalid_argument, errstr ); + + curDim_ = newstate.curDim; + int lclDim = MVT::GetNumberVecs(*newstate.V); + + // check size of H + TEST_FOR_EXCEPTION(newstate.H->numRows() < curDim_ || newstate.H->numCols() < curDim_, std::invalid_argument, errstr); + + if (curDim_ == 0 && lclDim > blockSize_) { + om_->stream(Warnings) << "Anasazi::BlockKrylovSchur::initialize(): the solver was initialized with a kernel of " << lclDim << std::endl + << "The block size however is only " << blockSize_ << std::endl + << "The last " << lclDim - blockSize_ << " vectors of the kernel will be overwritten on the first call to iterate()." << std::endl; + } + + + // copy basis vectors from newstate into V + if (newstate.V != V_) { + std::vector nevind(lclDim); + for (int i=0; iputScalar( ST_ZERO ); + Teuchos::SerialDenseMatrix newH(Teuchos::View,*newstate.H,curDim_+blockSize_,curDim_); + Teuchos::RCP > lclH; + lclH = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::View,*H_,curDim_+blockSize_,curDim_) ); + lclH->assign(newH); + + // done with local pointers + lclH = Teuchos::null; + } + + } + else { + // user did not specify a basis V + // get vectors from problem or generate something, projectAndNormalize, call initialize() recursively + Teuchos::RCP ivec = problem_->getInitVec(); + TEST_FOR_EXCEPTION(ivec == Teuchos::null,std::invalid_argument, + "Anasazi::BlockKrylovSchur::initialize(): eigenproblem did not specify initial vectors to clone from."); + + int lclDim = MVT::GetNumberVecs(*ivec); + bool userand = false; + if (lclDim < blockSize_) { + // we need at least blockSize_ vectors + // use a random multivec + userand = true; + } + + if (userand) { + // make an index + std::vector dimind2(lclDim); + for (int i=0; i newV1 = MVT::CloneView(*V_,dimind2); + + // copy the initial vectors into the first lclDim vectors of V + MVT::SetBlock(*ivec,dimind2,*newV1); + + // resize / reinitialize the index vector + dimind2.resize(blockSize_-lclDim); + for (int i=0; i newV2 = MVT::CloneView(*V_,dimind2); + MVT::MvRandom(*newV2); + } + else { + // alloc newV as a view of the first block of V + Teuchos::RCP newV1 = MVT::CloneView(*V_,bsind); + + // get a view of the first block of initial vectors + Teuchos::RCP ivecV = MVT::CloneView(*ivec,bsind); + + // assign ivec to first part of newV + MVT::SetBlock(*ivecV,bsind,*newV1); + } + + // get pointer into first block of V + Teuchos::RCP newV = MVT::CloneView(*V_,bsind); + + // remove auxVecs from newV and normalize newV + if (auxVecs_.size() > 0) { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + + Teuchos::Array > > dummy; + int rank = orthman_->projectAndNormalize(*newV,dummy,Teuchos::null,auxVecs_); + TEST_FOR_EXCEPTION( rank != blockSize_,BlockKrylovSchurInitFailure, + "Anasazi::BlockKrylovSchur::initialize(): couldn't generate initial basis of full rank." ); + } + else { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + + int rank = orthman_->normalize(*newV,Teuchos::null); + TEST_FOR_EXCEPTION( rank != blockSize_,BlockKrylovSchurInitFailure, + "Anasazi::BlockKrylovSchur::initialize(): couldn't generate initial basis of full rank." ); + } + + // set curDim + curDim_ = 0; + + // clear pointer + newV = Teuchos::null; + } + + // The Ritz vectors/values and Schur form are no longer current. + ritzVecsCurrent_ = false; + ritzValsCurrent_ = false; + schurCurrent_ = false; + + // the solver is initialized + initialized_ = true; + + if (om_->isVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkV = true; + chk.checkArn = true; + chk.checkAux = true; + om_->print( Debug, accuracyCheck(chk, ": after initialize()") ); + } + + // Print information on current status + if (om_->isVerbosity(Debug)) { + currentStatus( om_->stream(Debug) ); + } + else if (om_->isVerbosity(IterationDetails)) { + currentStatus( om_->stream(IterationDetails) ); + } + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // initialize the solver with default state + template + void BlockKrylovSchur::initialize() + { + BlockKrylovSchurState empty; + initialize(empty); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Perform BlockKrylovSchur iterations until the StatusTest tells us to stop. + template + void BlockKrylovSchur::iterate() + { + // + // Allocate/initialize data structures + // + if (initialized_ == false) { + initialize(); + } + + // Compute the current search dimension. + // If the problem is non-Hermitian and the blocksize is one, let the solver use the extra vector. + int searchDim = blockSize_*numBlocks_; + if (problem_->isHermitian() == false) { + searchDim++; + } + + //////////////////////////////////////////////////////////////// + // iterate until the status test tells us to stop. + // + // also break if our basis is full + // + while (tester_->checkStatus(this) != Passed && curDim_+blockSize_ <= searchDim) { + + iter_++; + + // F can be found at the curDim_ block, but the next block is at curDim_ + blockSize_. + int lclDim = curDim_ + blockSize_; + + // Get the current part of the basis. + std::vector curind(blockSize_); + for (int i=0; i Vnext = MVT::CloneView(*V_,curind); + + // Get a view of the previous vectors + // this is used for orthogonalization and for computing V^H K H + for (int i=0; i Vprev = MVT::CloneView(*V_,curind); + + // Compute the next vector in the Krylov basis: Vnext = Op*Vprev + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*Op_,*Vprev,*Vnext); + count_ApplyOp_ += blockSize_; + } + Vprev = Teuchos::null; + + // Remove all previous Krylov-Schur basis vectors and auxVecs from Vnext + { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + + // Get a view of all the previous vectors + std::vector prevind(lclDim); + for (int i=0; i > AVprev(1, Vprev); + + // Get a view of the part of the Hessenberg matrix needed to hold the ortho coeffs. + Teuchos::RCP > + subH = Teuchos::rcp( new Teuchos::SerialDenseMatrix + ( Teuchos::View,*H_,lclDim,blockSize_,0,curDim_ ) ); + Teuchos::Array > > AsubH; + AsubH.append( subH ); + + // Add the auxiliary vectors to the current basis vectors if any exist + if (auxVecs_.size() > 0) { + for (unsigned int i=0; i > + subR = Teuchos::rcp( new Teuchos::SerialDenseMatrix + ( Teuchos::View,*H_,blockSize_,blockSize_,lclDim,curDim_ ) ); + int rank = orthman_->projectAndNormalize(*Vnext,AsubH,subR,AVprev); + TEST_FOR_EXCEPTION(rank != blockSize_,BlockKrylovSchurOrthoFailure, + "Anasazi::BlockKrylovSchur::iterate(): couldn't generate basis of full rank."); + } + // + // V has been extended, and H has been extended. + // + // Update basis dim and release all pointers. + Vnext = Teuchos::null; + curDim_ += blockSize_; + // The Ritz vectors/values and Schur form are no longer current. + ritzVecsCurrent_ = false; + ritzValsCurrent_ = false; + schurCurrent_ = false; + // + // Update Ritz values and residuals if needed + if (!(iter_%stepSize_)) { + computeRitzValues(); + } + + // When required, monitor some orthogonalities + if (om_->isVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkV = true; + chk.checkArn = true; + om_->print( Debug, accuracyCheck(chk, ": after local update") ); + } + else if (om_->isVerbosity( OrthoDetails ) ) { + CheckList chk; + chk.checkV = true; + om_->print( OrthoDetails, accuracyCheck(chk, ": after local update") ); + } + + // Print information on current iteration + if (om_->isVerbosity(Debug)) { + currentStatus( om_->stream(Debug) ); + } + else if (om_->isVerbosity(IterationDetails)) { + currentStatus( om_->stream(IterationDetails) ); + } + + } // end while (statusTest == false) + + } // end of iterate() + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Check accuracy, orthogonality, and other debugging stuff + // + // bools specify which tests we want to run (instead of running more than we actually care about) + // + // checkV : V orthonormal + // orthogonal to auxvecs + // checkAux: check that auxiliary vectors are actually orthonormal + // + // checkArn: check the Arnoldi factorization + // + // NOTE: This method needs to check the current dimension of the subspace, since it is possible to + // call this method when curDim_ = 0 (after initialization). + template + std::string BlockKrylovSchur::accuracyCheck( const CheckList &chk, const std::string &where ) const + { + std::stringstream os; + os.precision(2); + os.setf(std::ios::scientific, std::ios::floatfield); + MagnitudeType tmp; + + os << " Debugging checks: iteration " << iter_ << where << std::endl; + + // index vectors for V and F + std::vector lclind(curDim_); + for (int i=0; i bsind(blockSize_); + for (int i=0; i lclV,lclF,lclAV; + if (curDim_) + lclV = MVT::CloneView(*V_,lclind); + lclF = MVT::CloneView(*V_,bsind); + + if (chk.checkV) { + if (curDim_) { + tmp = orthman_->orthonormError(*lclV); + os << " >> Error in V^H M V == I : " << tmp << std::endl; + } + tmp = orthman_->orthonormError(*lclF); + os << " >> Error in F^H M F == I : " << tmp << std::endl; + if (curDim_) { + tmp = orthman_->orthogError(*lclV,*lclF); + os << " >> Error in V^H M F == 0 : " << tmp << std::endl; + } + for (unsigned int i=0; iorthogError(*lclV,*auxVecs_[i]); + os << " >> Error in V^H M Aux[" << i << "] == 0 : " << tmp << std::endl; + } + tmp = orthman_->orthogError(*lclF,*auxVecs_[i]); + os << " >> Error in F^H M Aux[" << i << "] == 0 : " << tmp << std::endl; + } + } + + if (chk.checkArn) { + + if (curDim_) { + // Compute AV + Teuchos::RCP lclAV = MVT::Clone(*V_,curDim_); + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*Op_,*lclV,*lclAV); + } + + // Compute AV - VH + Teuchos::SerialDenseMatrix subH(Teuchos::View,*H_,curDim_,curDim_); + MVT::MvTimesMatAddMv( -ST_ONE, *lclV, subH, ST_ONE, *lclAV ); + + // Compute FB_k^T - (AV-VH) + Teuchos::SerialDenseMatrix curB(Teuchos::View,*H_, + blockSize_,curDim_, curDim_ ); + MVT::MvTimesMatAddMv( -ST_ONE, *lclF, curB, ST_ONE, *lclAV ); + + // Compute || FE_k^T - (AV-VH) || + std::vector arnNorms( curDim_ ); + orthman_->norm( *lclAV, &arnNorms ); + + for (int i=0; i> Error in Krylov-Schur factorization (R = AV-VS-FB^H), ||R[" << i << "]|| : " << arnNorms[i] << std::endl; + } + } + } + + if (chk.checkAux) { + for (unsigned int i=0; iorthonormError(*auxVecs_[i]); + os << " >> Error in Aux[" << i << "]^H M Aux[" << i << "] == I : " << tmp << std::endl; + for (unsigned int j=i+1; jorthogError(*auxVecs_[i],*auxVecs_[j]); + os << " >> Error in Aux[" << i << "]^H M Aux[" << j << "] == 0 : " << tmp << std::endl; + } + } + } + + os << std::endl; + + return os.str(); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + /* Get the current approximate eigenvalues, i.e. Ritz values. + * + * POST-CONDITIONS: + * + * ritzValues_ contains Ritz w.r.t. V, H + * Q_ contains the Schur vectors w.r.t. H + * schurH_ contains the Schur matrix w.r.t. H + * ritzOrder_ contains the current ordering from sort manager + */ + + template + void BlockKrylovSchur::computeRitzValues() + { + // Can only call this if the solver is initialized + if (initialized_) { + + // This just updates the Ritz values and residuals. + // --> ritzValsCurrent_ will be set to 'true' by this method. + if (!ritzValsCurrent_) { + // Compute the current Ritz values, through computing the Schur form + // without updating the current projection matrix or sorting the Schur form. + computeSchurForm( false ); + } + } + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + /* Get the current approximate eigenvectors, i.e. Ritz vectors. + * + * POST-CONDITIONS: + * + * ritzValues_ contains Ritz w.r.t. V, H + * ritzVectors_ is first blockSize_ Ritz vectors w.r.t. V, H + * Q_ contains the Schur vectors w.r.t. H + * schurH_ contains the Schur matrix w.r.t. H + * ritzOrder_ contains the current ordering from sort manager + */ + + template + void BlockKrylovSchur::computeRitzVectors() + { + Teuchos::TimeMonitor LocalTimer(*timerCompRitzVec_); + + TEST_FOR_EXCEPTION(numRitzVecs_==0, std::invalid_argument, + "Anasazi::BlockKrylovSchur::computeRitzVectors(): no Ritz vectors were required from this solver."); + + TEST_FOR_EXCEPTION(curDim_ < numRitzVecs_, std::invalid_argument, + "Anasazi::BlockKrylovSchur::computeRitzVectors(): the current subspace is not large enough to compute the number of requested Ritz vectors."); + + + // Check to see if the current subspace dimension is non-trivial and the solver is initialized + if (curDim_ && initialized_) { + + // Check to see if the Ritz vectors are current. + if (!ritzVecsCurrent_) { + + // Check to see if the Schur factorization of H (schurH_, Q) is current and sorted. + if (!schurCurrent_) { + // Compute the Schur factorization of the current H, which will not directly change H, + // the factorization will be sorted and placed in (schurH_, Q) + computeSchurForm( true ); + } + + // After the Schur form is computed, then the Ritz values are current. + // Thus, I can check the Ritz index vector to see if I have enough space for the Ritz vectors requested. + TEST_FOR_EXCEPTION(ritzIndex_[numRitzVecs_-1]==1, std::logic_error, + "Anasazi::BlockKrylovSchur::computeRitzVectors(): the number of required Ritz vectors splits a complex conjugate pair."); + + Teuchos::LAPACK lapack; + Teuchos::LAPACK lapack_mag; + + // Compute the Ritz vectors. + // --> For a Hermitian problem this is simply the current basis times the first numRitzVecs_ Schur vectors + // + // --> For a non-Hermitian problem, this involves solving the projected eigenproblem, then + // placing the product of the current basis times the first numRitzVecs_ Schur vectors times the + // eigenvectors of interest into the Ritz vectors. + + // Get a view of the current Krylov-Schur basis vectors and Schur vectors + std::vector curind( curDim_ ); + for (int i=0; i Vtemp = MVT::CloneView( *V_, curind ); + if (problem_->isHermitian()) { + // Get a view into the current Schur vectors + Teuchos::SerialDenseMatrix subQ( Teuchos::View, *Q_, curDim_, numRitzVecs_ ); + + // Compute the current Ritz vectors + MVT::MvTimesMatAddMv( ST_ONE, *Vtemp, subQ, ST_ZERO, *ritzVectors_ ); + + } else { + + // Get a view into the current Schur vectors. + Teuchos::SerialDenseMatrix subQ( Teuchos::View, *Q_, curDim_, curDim_ ); + + // Get a set of work vectors to hold the current Ritz vectors. + Teuchos::RCP tmpritzVectors_ = MVT::Clone( *V_, curDim_ ); + + // Compute the current Krylov-Schur vectors. + MVT::MvTimesMatAddMv( ST_ONE, *Vtemp, subQ, ST_ZERO, *tmpritzVectors_ ); + + // Now compute the eigenvectors of the Schur form + // Reset the dense matrix and compute the eigenvalues of the Schur form. + // + // Allocate the work space. This space will be used below for calls to: + // * TREVC (requires 3*N for real, 2*N for complex) + + int lwork = 3*curDim_; + std::vector work( lwork ); + std::vector rwork( curDim_ ); + char side = 'R'; + int mm, info = 0; + const int ldvl = 1; + ScalarType vl[ ldvl ]; + Teuchos::SerialDenseMatrix copyQ( Teuchos::Copy, *Q_, curDim_, curDim_ ); + lapack.TREVC( side, curDim_, schurH_->values(), schurH_->stride(), vl, ldvl, + copyQ.values(), copyQ.stride(), curDim_, &mm, &work[0], &rwork[0], &info ); + TEST_FOR_EXCEPTION(info != 0, std::logic_error, + "Anasazi::BlockKrylovSchur::computeRitzVectors(): TREVC returned info != 0."); + + // Get a view into the eigenvectors of the Schur form + Teuchos::SerialDenseMatrix subCopyQ( Teuchos::View, copyQ, curDim_, numRitzVecs_ ); + + // Convert back to Ritz vectors of the operator. + std::vector curind( (numRitzVecs_) ); + for (int i=0; i<(int)curind.size(); i++) { curind[i] = i; } + + Teuchos::RCP view_ritzVectors = MVT::CloneView( *ritzVectors_, curind ); + MVT::MvTimesMatAddMv( ST_ONE, *tmpritzVectors_, subCopyQ, ST_ZERO, *view_ritzVectors ); + + // Compute the norm of the new Ritz vectors + std::vector ritzNrm( numRitzVecs_ ); + MVT::MvNorm( *view_ritzVectors, &ritzNrm ); + + // Release memory used to compute Ritz vectors before scaling the current vectors. + tmpritzVectors_ = Teuchos::null; + view_ritzVectors = Teuchos::null; + + // Scale the Ritz vectors to have Euclidean norm. + ScalarType ritzScale = ST_ONE; + for (int i=0; i newind(2); + newind[0] = i; newind[1] = i+1; + tmpritzVectors_ = MVT::CloneCopy( *ritzVectors_, newind ); + view_ritzVectors = MVT::CloneView( *ritzVectors_, newind ); + MVT::MvAddMv( ritzScale, *tmpritzVectors_, ST_ZERO, *tmpritzVectors_, *view_ritzVectors ); + + // Increment counter for imaginary part + i++; + } else { + + // This is a real Ritz value, normalize the vector + std::vector newind(1); + newind[0] = i; + tmpritzVectors_ = MVT::CloneCopy( *ritzVectors_, newind ); + view_ritzVectors = MVT::CloneView( *ritzVectors_, newind ); + MVT::MvAddMv( ST_ONE/ritzNrm[i], *tmpritzVectors_, ST_ZERO, *tmpritzVectors_, *view_ritzVectors ); + } + } + + } // if (problem_->isHermitian()) + + // The current Ritz vectors have been computed. + ritzVecsCurrent_ = true; + + } // if (!ritzVecsCurrent_) + } // if (curDim_) + } // computeRitzVectors() + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + /* Get the current approximate eigenvalues, i.e. Ritz values. + * + * POST-CONDITIONS: + * + * ritzValues_ contains Ritz w.r.t. V, H + * Q_ contains the Schur vectors w.r.t. H + * schurH_ contains the Schur matrix w.r.t. H + * ritzOrder_ contains the current ordering from sort manager + * schurCurrent_ = true if sort = true; i.e. the Schur form is sorted according to the index + * vector returned by the sort manager. + */ + template + void BlockKrylovSchur::computeSchurForm( const bool sort ) + { + // local timer + Teuchos::TimeMonitor LocalTimer(*timerCompSF_); + + // Check to see if the dimension of the factorization is greater than zero. + if (curDim_) { + + // Check to see if the Schur factorization is current. + if (!schurCurrent_) { + + // Check to see if the Ritz values are current + // --> If they are then the Schur factorization is current but not sorted. + if (!ritzValsCurrent_) { + Teuchos::LAPACK lapack; + Teuchos::LAPACK lapack_mag; + Teuchos::BLAS blas; + Teuchos::BLAS blas_mag; + + // Get a view into Q, the storage for H's Schur vectors. + Teuchos::SerialDenseMatrix subQ( Teuchos::View, *Q_, curDim_, curDim_ ); + + // Get a copy of H to compute/sort the Schur form. + schurH_ = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, *H_, curDim_, curDim_ ) ); + // + //--------------------------------------------------- + // Compute the Schur factorization of subH + // ---> Use driver GEES to first reduce to upper Hessenberg + // form and then compute Schur form, outputting Ritz values + //--------------------------------------------------- + // + // Allocate the work space. This space will be used below for calls to: + // * GEES (requires 3*N for real, 2*N for complex) + // * TREVC (requires 3*N for real, 2*N for complex) + // * TREXC (requires N for real, none for complex) + // Furthermore, GEES requires a real array of length curDim_ (for complex datatypes) + // + int lwork = 3*curDim_; + std::vector work( lwork ); + std::vector rwork( curDim_ ); + std::vector tmp_rRitzValues( curDim_ ); + std::vector tmp_iRitzValues( curDim_ ); + std::vector bwork( curDim_ ); + int info = 0, sdim = 0; + char jobvs = 'V'; + lapack.GEES( jobvs,curDim_, schurH_->values(), schurH_->stride(), &sdim, &tmp_rRitzValues[0], + &tmp_iRitzValues[0], subQ.values(), subQ.stride(), &work[0], lwork, + &rwork[0], &bwork[0], &info ); + + TEST_FOR_EXCEPTION(info != 0, std::logic_error, + "Anasazi::BlockKrylovSchur::computeSchurForm(): GEES returned info != 0."); + // + //--------------------------------------------------- + // Use the Krylov-Schur factorization to compute the current Ritz residuals + // for ALL the eigenvalues estimates (Ritz values) + // || Ax - x\theta || = || U_m+1*B_m+1^H*Q*s || + // = || B_m+1^H*Q*s || + // + // where U_m+1 is the current Krylov-Schur basis, Q are the Schur vectors, and x = U_m+1*Q*s + // NOTE: This means that s = e_i if the problem is hermitian, else the eigenvectors + // of the Schur form need to be computed. + // + // First compute H_{m+1,m}*B_m^T, then determine what 's' is. + //--------------------------------------------------- + // + // Get current B_m+1 + Teuchos::SerialDenseMatrix curB(Teuchos::View, *H_, + blockSize_, curDim_, curDim_ ); + // + // Compute B_m+1^H*Q + Teuchos::SerialDenseMatrix subB( blockSize_, curDim_ ); + blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, blockSize_, curDim_, curDim_, ST_ONE, + curB.values(), curB.stride(), subQ.values(), subQ.stride(), + ST_ZERO, subB.values(), subB.stride() ); + // + // Determine what 's' is and compute Ritz residuals. + // + ScalarType* b_ptr = subB.values(); + if (problem_->isHermitian()) { + // + // 's' is the i-th canonical basis vector. + // + for (int i=0; i S( curDim_, curDim_ ); + lapack.TREVC( side, curDim_, schurH_->values(), schurH_->stride(), vl, ldvl, + S.values(), S.stride(), curDim_, &mm, &work[0], &rwork[0], &info ); + + TEST_FOR_EXCEPTION(info != 0, std::logic_error, + "Anasazi::BlockKrylovSchur::computeSchurForm(): TREVC returned info != 0."); + // + // Scale the eigenvectors so that their Euclidean norms are all one. + // + scaleRitzVectors( tmp_iRitzValues, &S ); + // + // Compute ritzRes = *B_m+1^H*Q*S where the i-th column of S is 's' for the i-th Ritz-value + // + Teuchos::SerialDenseMatrix ritzRes( blockSize_, curDim_ ); + blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, blockSize_, curDim_, curDim_, ST_ONE, + subB.values(), subB.stride(), S.values(), S.stride(), + ST_ZERO, ritzRes.values(), ritzRes.stride() ); + + /* TO DO: There's be an incorrect assumption made in the computation of the Ritz residuals. + This assumption is that the next vector in the Krylov subspace is Euclidean orthonormal. + It may not be normalized using Euclidean norm. + Teuchos::RCP ritzResVecs = MVT::Clone( *V_, curDim_ ); + std::vector curind(blockSize_); + for (int i=0; i Vtemp = MVT::CloneView(*V_,curind); + + MVT::MvTimesMatAddMv( ST_ONE, *Vtemp, ritzRes, ST_ZERO, *ritzResVecs ); + std::vector ritzResNrms(curDim_); + MVT::MvNorm( *ritzResVecs, &ritzResNrms ); + i = 0; + while( i < curDim_ ) { + if ( tmp_ritzValues[curDim_+i] != MT_ZERO ) { + ritzResiduals_[i] = lapack_mag.LAPY2( ritzResNrms[i], ritzResNrms[i+1] ); + ritzResiduals_[i+1] = ritzResiduals_[i]; + i = i+2; + } else { + ritzResiduals_[i] = ritzResNrms[i]; + i++; + } + } + */ + // + // Compute the Ritz residuals for each Ritz value. + // + computeRitzResiduals( tmp_iRitzValues, ritzRes, &ritzResiduals_ ); + } + // + // Sort the Ritz values. + // + { + Teuchos::TimeMonitor LocalTimer2(*timerSortRitzVal_); + int i=0; + if (problem_->isHermitian()) { + // + // Sort using just the real part of the Ritz values. + sm_->sort( this, curDim_, tmp_rRitzValues, &ritzOrder_ ); // don't catch exception + ritzIndex_.clear(); + while ( i < curDim_ ) { + // The Ritz value is not complex. + ritzValues_[i].set(tmp_rRitzValues[i], MT_ZERO); + ritzIndex_.push_back(0); + i++; + } + } + else { + // + // Sort using both the real and imaginary parts of the Ritz values. + sm_->sort( this, curDim_, tmp_rRitzValues, tmp_iRitzValues, &ritzOrder_ ); + sortRitzValues( tmp_rRitzValues, tmp_iRitzValues, &ritzValues_, &ritzOrder_, &ritzIndex_ ); + } + // + // Sort the ritzResiduals_ based on the ordering from the Sort Manager. + std::vector ritz2( curDim_ ); + for (int i=0; i + void BlockKrylovSchur::sortSchurForm( Teuchos::SerialDenseMatrix& H, + Teuchos::SerialDenseMatrix& Q, + std::vector& order ) + { + // local timer + Teuchos::TimeMonitor LocalTimer(*timerSortSF_); + // + //--------------------------------------------------- + // Reorder real Schur factorization, remember to add one to the indices for the + // fortran call and determine offset. The offset is necessary since the TREXC + // method reorders in a nonsymmetric fashion, thus we use the reordering in + // a stack-like fashion. Also take into account conjugate pairs, which may mess + // up the reordering, since the pair is moved if one of the pair is moved. + //--------------------------------------------------- + // + int i = 0, nevtemp = 0; + char compq = 'V'; + std::vector offset2( curDim_ ); + std::vector order2( curDim_ ); + + // LAPACK objects. + Teuchos::LAPACK lapack; + int lwork = 3*curDim_; + std::vector work( lwork ); + + while (i < curDim_) { + if ( ritzIndex_[i] != 0 ) { // This is the first value of a complex conjugate pair + offset2[nevtemp] = 0; + for (int j=i; j order[i]) { offset2[nevtemp]++; } + } + order2[nevtemp] = order[i]; + i = i+2; + } else { + offset2[nevtemp] = 0; + for (int j=i; j order[i]) { offset2[nevtemp]++; } + } + order2[nevtemp] = order[i]; + i++; + } + nevtemp++; + } + ScalarType *ptr_h = H.values(); + ScalarType *ptr_q = Q.values(); + int ldh = H.stride(), ldq = Q.stride(); + int info = 0; + for (i=nevtemp-1; i>=0; i--) { + lapack.TREXC( compq, curDim_, ptr_h, ldh, ptr_q, ldq, order2[i]+1+offset2[i], + 1, &work[0], &info ); + TEST_FOR_EXCEPTION(info != 0, std::logic_error, + "Anasazi::BlockKrylovSchur::computeSchurForm(): TREXC returned info != 0."); + } + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Print the current status of the solver + template + void BlockKrylovSchur::currentStatus(std::ostream &os) + { + using std::endl; + + os.setf(std::ios::scientific, std::ios::floatfield); + os.precision(6); + os <<"================================================================================" << endl; + os << endl; + os <<" BlockKrylovSchur Solver Status" << endl; + os << endl; + os <<"The solver is "<<(initialized_ ? "initialized." : "not initialized.") << endl; + os <<"The number of iterations performed is " <isHermitian()) { + os << std::setw(20) << "Ritz Value" + << std::setw(20) << "Ritz Residual" + << endl; + os <<"--------------------------------------------------------------------------------"<::magnitude(ritzValues_[i].imagpart); + } else { + os << " + i" << std::setw(15) << ritzValues_[i].imagpart; + } + os << std::setw(20) << ritzResiduals_[i] << endl; + } + } + } else { + os << std::setw(20) << "[ NONE COMPUTED ]" << endl; + } + } + os << endl; + os <<"================================================================================" << endl; + os << endl; + } + +} // End of namespace Anasazi + +#endif + +// End of file AnasaziBlockKrylovSchur.hpp diff --git a/fastlib/trilinos/include/AnasaziBlockKrylovSchurSolMgr.hpp b/fastlib/trilinos/include/AnasaziBlockKrylovSchurSolMgr.hpp new file mode 100644 index 0000000000..c3337e8871 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziBlockKrylovSchurSolMgr.hpp @@ -0,0 +1,634 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP +#define ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP + +/*! \file AnasaziBlockKrylovSchurSolMgr.hpp + * \brief The Anasazi::BlockKrylovSchurSolMgr provides a solver manager for the BlockKrylovSchur eigensolver. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +#include "AnasaziEigenproblem.hpp" +#include "AnasaziSolverManager.hpp" + +#include "AnasaziBlockKrylovSchur.hpp" +#include "AnasaziBasicSort.hpp" +#include "AnasaziSVQBOrthoManager.hpp" +#include "AnasaziBasicOrthoManager.hpp" +#include "AnasaziStatusTestMaxIters.hpp" +#include "AnasaziStatusTestResNorm.hpp" +#include "AnasaziStatusTestOrderedResNorm.hpp" +#include "AnasaziStatusTestCombo.hpp" +#include "AnasaziStatusTestOutput.hpp" +#include "AnasaziBasicOutputManager.hpp" +#include "AnasaziSolverUtils.hpp" +#include "Teuchos_BLAS.hpp" +#include "Teuchos_LAPACK.hpp" +#include "Teuchos_TimeMonitor.hpp" + +/** \example BlockKrylovSchur/BlockKrylovSchurEpetraEx.cpp + This is an example of how to use the Anasazi::BlockKrylovSchurSolMgr solver manager. +*/ + +/*! \class Anasazi::BlockKrylovSchurSolMgr + * + * \brief The Anasazi::BlockKrylovSchurSolMgr provides a powerful and fully-featured solver manager over the BlockKrylovSchur eigensolver. + + \ingroup anasazi_solver_framework + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, Heidi Thornquist + */ + +namespace Anasazi { + +template +class BlockKrylovSchurSolMgr : public SolverManager { + + private: + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + typedef Teuchos::ScalarTraits SCT; + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + public: + + //! @name Constructors/Destructor + //@{ + + /*! \brief Basic constructor for BlockKrylovSchurSolMgr. + * + * This constructor accepts the Eigenproblem to be solved in addition + * to a parameter list of options for the solver manager. These options include the following: + * - "Which" - a \c string specifying the desired eigenvalues: SM, LM, SR or LR. Default: "LM" + * - "Block Size" - a \c int specifying the block size to be used by the underlying block Krylov-Schur solver. Default: 1 + * - "Num Blocks" - a \c int specifying the number of blocks allocated for the Krylov basis. Default: 3*nev + * - "Extra NEV Blocks" - a \c int specifying the number of extra blocks the solver should keep in addition to those + required to compute the number of eigenvalues requested. Default: 0 + * - "Maximum Restarts" - a \c int specifying the maximum number of restarts the underlying solver is allowed to perform. Default: 20 + * - "Orthogonalization" - a \c string specifying the desired orthogonalization: DGKS and SVQB. Default: "SVQB" + * - "Verbosity" - a sum of MsgType specifying the verbosity. Default: Anasazi::Errors + * - "Convergence Tolerance" - a \c MagnitudeType specifying the level that residual norms must reach to decide convergence. Default: machine precision. + * - "Relative Convergence Tolerance" - a \c bool specifying whether residuals norms should be scaled by their eigenvalues for the purposing of deciding convergence. Default: true + */ + BlockKrylovSchurSolMgr( const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ); + + //! Destructor. + virtual ~BlockKrylovSchurSolMgr() {}; + //@} + + //! @name Accessor methods + //@{ + + const Eigenproblem& getProblem() const { + return *_problem; + } + + /*! \brief Return the Ritz values from the most recent solve. + */ + std::vector > getRitzValues() const { + std::vector > ret( _ritzValues ); + return ret; + } + + /*! \brief Return the timers for this object. + * + * The timers are ordered as follows: + * - time spent in solve() routine + * - time spent restarting + */ + Teuchos::Array > getTimers() const { + return tuple(_timerSolve, _timerRestarting); + } + + //@} + + //! @name Solver application methods + //@{ + + /*! \brief This method performs possibly repeated calls to the underlying eigensolver's iterate() routine + * until the problem has been solved (as decided by the solver manager) or the solver manager decides to + * quit. + * + * This method calls BlockKrylovSchur::iterate(), which will return either because a specially constructed status test evaluates to ::Passed + * or an exception is thrown. + * + * A return from BlockKrylovSchur::iterate() signifies one of the following scenarios: + * - the maximum number of restarts has been exceeded. In this scenario, the solver manager will place\n + * all converged eigenpairs into the eigenproblem and return ::Unconverged. + * - global convergence has been met. In this case, the most significant NEV eigenpairs in the solver and locked storage \n + * have met the convergence criterion. (Here, NEV refers to the number of eigenpairs requested by the Eigenproblem.) \n + * In this scenario, the solver manager will return ::Converged. + * + * \returns ::ReturnType specifying: + * - ::Converged: the eigenproblem was solved to the specification required by the solver manager. + * - ::Unconverged: the eigenproblem was not solved to the specification desired by the solver manager. + */ + ReturnType solve(); + //@} + + private: + Teuchos::RCP > _problem; + Teuchos::RCP > _sort; + + std::string _whch, _ortho; + MagnitudeType _ortho_kappa; + + MagnitudeType _convtol; + int _maxRestarts; + bool _relconvtol,_conjSplit; + int _blockSize, _numBlocks, _stepSize, _nevBlocks, _xtra_nevBlocks; + int _verbosity; + bool _inSituRestart; + + std::vector > _ritzValues; + + Teuchos::RCP _timerSolve, _timerRestarting; + +}; + + +// Constructor +template +BlockKrylovSchurSolMgr::BlockKrylovSchurSolMgr( + const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ) : + _problem(problem), + _whch("LM"), + _ortho("SVQB"), + _ortho_kappa(-1.0), + _convtol(0), + _maxRestarts(20), + _relconvtol(true), + _conjSplit(false), + _blockSize(0), + _numBlocks(0), + _stepSize(0), + _nevBlocks(0), + _xtra_nevBlocks(0), + _verbosity(Anasazi::Errors), + _inSituRestart(false), + _timerSolve(Teuchos::TimeMonitor::getNewTimer("BKSSolMgr::solve()")), + _timerRestarting(Teuchos::TimeMonitor::getNewTimer("BKSSolMgr restarting")) +{ + TEST_FOR_EXCEPTION(_problem == Teuchos::null, std::invalid_argument, "Problem not given to solver manager."); + TEST_FOR_EXCEPTION(!_problem->isProblemSet(), std::invalid_argument, "Problem not set."); + TEST_FOR_EXCEPTION(_problem->getInitVec() == Teuchos::null, std::invalid_argument, "Problem does not contain initial vectors to clone from."); + + const int nev = _problem->getNEV(); + + // convergence tolerance + _convtol = pl.get("Convergence Tolerance",MT::prec()); + _relconvtol = pl.get("Relative Convergence Tolerance",_relconvtol); + + // maximum number of restarts + _maxRestarts = pl.get("Maximum Restarts",_maxRestarts); + + // block size: default is 1 + _blockSize = pl.get("Block Size",1); + TEST_FOR_EXCEPTION(_blockSize <= 0, std::invalid_argument, + "Anasazi::BlockKrylovSchurSolMgr: \"Block Size\" must be strictly positive."); + + // set the number of blocks we need to save to compute the nev eigenvalues of interest. + _xtra_nevBlocks = pl.get("Extra NEV Blocks",0); + if (nev%_blockSize) { + _nevBlocks = nev/_blockSize + _xtra_nevBlocks + 1; + } else { + _nevBlocks = nev/_blockSize + _xtra_nevBlocks; + } + + _numBlocks = pl.get("Num Blocks",3*_nevBlocks); + TEST_FOR_EXCEPTION(_numBlocks <= _nevBlocks, std::invalid_argument, + "Anasazi::BlockKrylovSchurSolMgr: \"Num Blocks\" must be strictly positive and large enough to compute the requested eigenvalues."); + + TEST_FOR_EXCEPTION(_numBlocks*_blockSize > MVT::GetVecLength(*_problem->getInitVec()), + std::invalid_argument, + "Anasazi::BlockKrylovSchurSolMgr: Potentially impossible orthogonality requests. Reduce basis size."); + + // step size: the default is _maxRestarts*_numBlocks, so that Ritz values are only computed every restart. + if (_maxRestarts) { + _stepSize = pl.get("Step Size", (_maxRestarts+1)*(_numBlocks+1)); + } else { + _stepSize = pl.get("Step Size", _numBlocks+1); + } + TEST_FOR_EXCEPTION(_stepSize < 1, std::invalid_argument, + "Anasazi::BlockKrylovSchurSolMgr: \"Step Size\" must be strictly positive."); + + // get the sort manager + if (pl.isParameter("Sort Manager")) { + _sort = Teuchos::getParameter > >(pl,"Sort Manager"); + } else { + // which values to solve for + _whch = pl.get("Which",_whch); + TEST_FOR_EXCEPTION(_whch != "SM" && _whch != "LM" && _whch != "SR" && _whch != "LR" && _whch != "SI" && _whch != "LI", + std::invalid_argument, "Invalid sorting string."); + _sort = Teuchos::rcp( new BasicSort(_whch) ); + } + + // which orthogonalization to use + _ortho = pl.get("Orthogonalization",_ortho); + if (_ortho != "DGKS" && _ortho != "SVQB") { + _ortho = "SVQB"; + } + + // which orthogonalization constant to use + _ortho_kappa = pl.get("Orthogonalization Constant",_ortho_kappa); + + // verbosity level + if (pl.isParameter("Verbosity")) { + if (Teuchos::isParameterType(pl,"Verbosity")) { + _verbosity = pl.get("Verbosity", _verbosity); + } else { + _verbosity = (int)Teuchos::getParameter(pl,"Verbosity"); + } + } + + // restarting technique: V*Q or applyHouse(V,H,tau) + if (pl.isParameter("In Situ Restarting")) { + if (Teuchos::isParameterType(pl,"In Situ Restarting")) { + _inSituRestart = pl.get("In Situ Restarting",_inSituRestart); + } else { + _inSituRestart = (bool)Teuchos::getParameter(pl,"In Situ Restarting"); + } + } +} + + +// solve() +template +ReturnType +BlockKrylovSchurSolMgr::solve() { + + const int nev = _problem->getNEV(); + ScalarType one = Teuchos::ScalarTraits::one(); + ScalarType zero = Teuchos::ScalarTraits::zero(); + + Teuchos::BLAS blas; + Teuchos::LAPACK lapack; + typedef SolverUtils msutils; + + ////////////////////////////////////////////////////////////////////////////////////// + // Output manager + Teuchos::RCP > printer = Teuchos::rcp( new BasicOutputManager(_verbosity) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Status tests + // + // convergence + Teuchos::RCP > convtest + = Teuchos::rcp( new StatusTestOrderedResNorm(_sort,_convtol,nev,StatusTestOrderedResNorm::RITZRES_2NORM,_relconvtol) ); + + // printing StatusTest + Teuchos::RCP > outputtest + = Teuchos::rcp( new StatusTestOutput( printer,convtest,1,Passed ) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Orthomanager + // + Teuchos::RCP > ortho; + if (_ortho=="SVQB") { + ortho = Teuchos::rcp( new SVQBOrthoManager(_problem->getM()) ); + } else if (_ortho=="DGKS") { + if (_ortho_kappa <= 0) { + ortho = Teuchos::rcp( new BasicOrthoManager(_problem->getM()) ); + } + else { + ortho = Teuchos::rcp( new BasicOrthoManager(_problem->getM(),_ortho_kappa) ); + } + } else { + TEST_FOR_EXCEPTION(_ortho!="SVQB"&&_ortho!="DGKS",std::logic_error,"Anasazi::BlockKrylovSchurSolMgr::solve(): Invalid orthogonalization type."); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // Parameter list + Teuchos::ParameterList plist; + plist.set("Block Size",_blockSize); + plist.set("Num Blocks",_numBlocks); + plist.set("Step Size",_stepSize); + plist.set("Print Number of Ritz Values",_nevBlocks*_blockSize); + + ////////////////////////////////////////////////////////////////////////////////////// + // BlockKrylovSchur solver + Teuchos::RCP > bks_solver + = Teuchos::rcp( new BlockKrylovSchur(_problem,_sort,printer,outputtest,ortho,plist) ); + // set any auxiliary vectors defined in the problem + Teuchos::RCP< const MV > probauxvecs = _problem->getAuxVecs(); + if (probauxvecs != Teuchos::null) { + bks_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP >(probauxvecs) ); + } + + // Create workspace for the Krylov basis generated during a restart + // Need at most (_nevBlocks*_blockSize+1) for the updated factorization and another block for the current factorization residual block (F). + // ---> (_nevBlocks*_blockSize+1) + _blockSize + // If Hermitian, this becomes _nevBlocks*_blockSize + _blockSize + // we only need this if there is the possibility of restarting, ex situ + Teuchos::RCP workMV; + if (_maxRestarts > 0) { + if (_inSituRestart==true) { + // still need one work vector for applyHouse() + workMV = MVT::Clone( *_problem->getInitVec(), 1 ); + } + else { // inSituRestart == false + if (_problem->isHermitian()) { + workMV = MVT::Clone( *_problem->getInitVec(), _nevBlocks*_blockSize + _blockSize ); + } else { + workMV = MVT::Clone( *_problem->getInitVec(), _nevBlocks*_blockSize+1 + _blockSize ); + } + } + } else { + workMV = Teuchos::null; + } + + // go ahead and initialize the solution to nothing in case we throw an exception + Eigensolution sol; + sol.numVecs = 0; + _problem->setSolution(sol); + + int numRestarts = 0; + int cur_nevBlocks = 0; + + // enter solve() iterations + { + Teuchos::TimeMonitor slvtimer(*_timerSolve); + + // tell bks_solver to iterate + while (1) { + try { + bks_solver->iterate(); + + //////////////////////////////////////////////////////////////////////////////////// + // + // check convergence first + // + //////////////////////////////////////////////////////////////////////////////////// + if (convtest->getStatus() == Passed ) { + // we have convergence + // convtest->whichVecs() tells us which vectors from solver state are the ones we want + // convtest->howMany() will tell us how many + break; + } + //////////////////////////////////////////////////////////////////////////////////// + // + // check for restarting, i.e. the subspace is full + // + //////////////////////////////////////////////////////////////////////////////////// + // this is for the Hermitian case, or non-Hermitian conjugate split situation. + // --> for the Hermitian case the current subspace dimension needs to match the maximum subspace dimension + // --> for the non-Hermitian case: + // --> if a conjugate pair was detected in the previous restart then the current subspace dimension needs to match the + // maximum subspace dimension (the BKS solver keeps one extra vector if the problem is non-Hermitian). + // --> if a conjugate pair was not detected in the previous restart then the current subspace dimension will be one less + // than the maximum subspace dimension. + else if ( (bks_solver->getCurSubspaceDim() == bks_solver->getMaxSubspaceDim()) || + (!_problem->isHermitian() && !_conjSplit && (bks_solver->getCurSubspaceDim()+1 == bks_solver->getMaxSubspaceDim())) ) { + + Teuchos::TimeMonitor restimer(*_timerRestarting); + + if ( numRestarts >= _maxRestarts ) { + break; // break from while(1){bks_solver->iterate()} + } + numRestarts++; + + printer->stream(Debug) << " Performing restart number " << numRestarts << " of " << _maxRestarts << std::endl << std::endl; + + // Update the Schur form of the projected eigenproblem, then sort it. + if (!bks_solver->isSchurCurrent()) + bks_solver->computeSchurForm( true ); + + // Get the most current Ritz values before we continue. + _ritzValues = bks_solver->getRitzValues(); + + // Get the state. + BlockKrylovSchurState oldState = bks_solver->getState(); + + // Get the current dimension of the factorization + int curDim = oldState.curDim; + + // Determine if the storage for the nev eigenvalues of interest splits a complex conjugate pair. + std::vector ritzIndex = bks_solver->getRitzIndex(); + if (ritzIndex[_nevBlocks*_blockSize-1]==1) { + _conjSplit = true; + cur_nevBlocks = _nevBlocks*_blockSize+1; + } else { + _conjSplit = false; + cur_nevBlocks = _nevBlocks*_blockSize; + } + + // Update the Krylov-Schur decomposition + + // Get a view of the Schur vectors of interest. + Teuchos::SerialDenseMatrix Qnev(Teuchos::View, *(oldState.Q), curDim, cur_nevBlocks); + + // Get a view of the current Krylov basis. + std::vector curind( curDim ); + for (int i=0; i basistemp = MVT::CloneView( *(oldState.V), curind ); + + // Compute the new Krylov basis: Vnew = V*Qnev + // + // this will occur ex situ in workspace allocated for this purpose (tmpMV) + // or in situ in the solver's memory space. + // + // we will also set a pointer for the location that the current factorization residual block (F), + // currently located after the current basis in oldstate.V, will be moved to + // + Teuchos::RCP newF; + if (_inSituRestart) { + // + // get non-const pointer to solver's basis so we can work in situ + Teuchos::RCP solverbasis = Teuchos::rcp_const_cast(oldState.V); + Teuchos::SerialDenseMatrix copyQnev(Qnev); + // + // perform Householder QR of copyQnev = Q [D;0], where D is unit diag. We will want D below. + std::vector tau(cur_nevBlocks), work(cur_nevBlocks); + int info; + lapack.GEQRF(curDim,cur_nevBlocks,copyQnev.values(),copyQnev.stride(),&tau[0],&work[0],work.size(),&info); + TEST_FOR_EXCEPTION(info != 0,std::logic_error, + "Anasazi::BlockDavidsonSolMgr::solve(): error calling GEQRF during restarting."); + // we need to get the diagonal of D + std::vector d(cur_nevBlocks); + for (int j=0; jisVerbosity(Debug)) { + Teuchos::SerialDenseMatrix R(Teuchos::Copy,copyQnev,cur_nevBlocks,cur_nevBlocks); + for (int j=0; jstream(Debug) << "||Triangular factor of Su - I||: " << R.normFrobenius() << std::endl; + } + // + // perform implicit V*Qnev + // this actually performs V*[Qnev Qtrunc*M] = [newV truncV], for some unitary M + // we are interested in only the first cur_nevBlocks vectors of the result + curind.resize(curDim); + for (int i=0; i oldV = MVT::CloneView(*solverbasis,curind); + msutils::applyHouse(cur_nevBlocks,*oldV,copyQnev,tau,workMV); + // clear pointer + oldV = Teuchos::null; + // multiply newV*D + // get pointer to new basis + curind.resize(cur_nevBlocks); + for (int i=0; i tmp_newV = MVT::CloneView(*workMV, curind ); + // perform V*Qnev + MVT::MvTimesMatAddMv( one, *basistemp, Qnev, zero, *tmp_newV ); + tmp_newV = Teuchos::null; + // get pointer to new location for F + curind.resize(_blockSize); + for (int i=0; i<_blockSize; i++) { curind[i] = cur_nevBlocks + i; } + newF = MVT::CloneView( *workMV, curind ); + } + + // Move the current factorization residual block (F) to the last block of newV. + curind.resize(_blockSize); + for (int i=0; i<_blockSize; i++) { curind[i] = curDim + i; } + Teuchos::RCP oldF = MVT::CloneView( *(oldState.V), curind ); + for (int i=0; i<_blockSize; i++) { curind[i] = i; } + MVT::SetBlock( *oldF, curind, *newF ); + newF = Teuchos::null; + + // Update the Krylov-Schur quasi-triangular matrix. + // + // Create storage for the new Schur matrix of the Krylov-Schur factorization + // Copy over the current quasi-triangular factorization of oldState.H which is stored in oldState.S. + Teuchos::SerialDenseMatrix oldS(Teuchos::View, *(oldState.S), cur_nevBlocks+_blockSize, cur_nevBlocks); + Teuchos::RCP > newH = + Teuchos::rcp( new Teuchos::SerialDenseMatrix( oldS ) ); + // + // Get a view of the B block of the current factorization + Teuchos::SerialDenseMatrix oldB(Teuchos::View, *(oldState.H), _blockSize, _blockSize, curDim, curDim-_blockSize); + // + // Get a view of the a block row of the Schur vectors. + Teuchos::SerialDenseMatrix subQ(Teuchos::View, *(oldState.Q), _blockSize, cur_nevBlocks, curDim-_blockSize); + // + // Get a view of the new B block of the updated Krylov-Schur factorization + Teuchos::SerialDenseMatrix newB(Teuchos::View, *newH, _blockSize, cur_nevBlocks, cur_nevBlocks); + // + // Compute the new B block. + blas.GEMM( Teuchos::NO_TRANS, Teuchos::NO_TRANS, _blockSize, cur_nevBlocks, _blockSize, one, + oldB.values(), oldB.stride(), subQ.values(), subQ.stride(), zero, newB.values(), newB.stride() ); + + + // + // Set the new state and initialize the solver. + BlockKrylovSchurState newstate; + if (_inSituRestart) { + newstate.V = oldState.V; + } else { + newstate.V = workMV; + } + newstate.H = newH; + newstate.curDim = cur_nevBlocks; + bks_solver->initialize(newstate); + + } // end of restarting + //////////////////////////////////////////////////////////////////////////////////// + // + // we returned from iterate(), but none of our status tests Passed. + // something is wrong, and it is probably our fault. + // + //////////////////////////////////////////////////////////////////////////////////// + else { + TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::BlockKrylovSchurSolMgr::solve(): Invalid return from bks_solver::iterate()."); + } + } + catch (std::exception e) { + printer->stream(Errors) << "Error! Caught exception in BlockKrylovSchur::iterate() at iteration " << bks_solver->getNumIters() << std::endl + << e.what() << std::endl; + throw; + } + } + + // + // free temporary space + workMV = Teuchos::null; + + // Get the most current Ritz values before we return + _ritzValues = bks_solver->getRitzValues(); + + sol.numVecs = convtest->howMany(); + if (sol.numVecs > 0) { + sol.index = bks_solver->getRitzIndex(); + sol.Evals = bks_solver->getRitzValues(); + // Check to see if conjugate pair is on the boundary. + if (sol.index[sol.numVecs-1]==1) { + sol.numVecs++; + sol.Evals.resize(sol.numVecs); + sol.index.resize(sol.numVecs); + bks_solver->setNumRitzVectors(sol.numVecs); + } else { + sol.Evals.resize(sol.numVecs); + sol.index.resize(sol.numVecs); + bks_solver->setNumRitzVectors(sol.numVecs); + } + bks_solver->computeRitzVectors(); + sol.Evecs = MVT::CloneCopy( *(bks_solver->getRitzVectors()) ); + sol.Espace = sol.Evecs; + } + } + + // print final summary + bks_solver->currentStatus(printer->stream(FinalSummary)); + + // print timing information + Teuchos::TimeMonitor::summarize(printer->stream(TimingDetails)); + + _problem->setSolution(sol); + printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl; + + if (sol.numVecs < nev) { + return Unconverged; // return from BlockKrylovSchurSolMgr::solve() + } + return Converged; // return from BlockKrylovSchurSolMgr::solve() +} + + +} // end Anasazi namespace + +#endif /* ANASAZI_BLOCK_KRYLOV_SCHUR_SOLMGR_HPP */ diff --git a/fastlib/trilinos/include/AnasaziConfigDefs.hpp b/fastlib/trilinos/include/AnasaziConfigDefs.hpp new file mode 100644 index 0000000000..003913dbdc --- /dev/null +++ b/fastlib/trilinos/include/AnasaziConfigDefs.hpp @@ -0,0 +1,188 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziConfigDefs.hpp + \brief Anasazi header file which uses auto-configuration information to include + necessary C++ headers +*/ + +#ifndef ANASAZI_CONFIGDEFS_HPP +#define ANASAZI_CONFIGDEFS_HPP + +#ifndef __cplusplus +#define __cplusplus +#endif + +#ifdef HAVE_CONFIG_H + +/* + * The macros PACKAGE, PACKAGE_NAME, etc, get defined for each package and need to + * be undef'd here to avoid warnings when this file is included from another package. + * KL 11/25/02 + */ +#ifdef PACKAGE +#undef PACKAGE +#endif + +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif + +#ifdef PACKAGE_BUGREPORT +#undef PACKAGE_BUGREPORT +#endif + +#ifdef PACKAGE_STRING +#undef PACKAGE_STRING +#endif + +#ifdef PACKAGE_TARNAME +#undef PACKAGE_TARNAME +#endif + +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif + +#ifdef VERSION +#undef VERSION +#endif + +#include + +#ifdef HAVE_MPI +#ifndef EPETRA_MPI +#define EPETRA_MPI +#endif +#endif + +#ifdef HAVE_CSTDLIB +#include +#else +#include +#endif + +#ifdef HAVE_CSTDIO +#include +#else +#include +#endif + +#ifdef HAVE_STRING +#include +#else +#include +#endif + +#ifdef HAVE_VECTOR +#include +#else +#include +#endif + +#ifdef HAVE_NUMERIC +#include +#else +#include +#endif + +#ifdef HAVE_COMPLEX +#include +#else +#include +#endif + +#ifdef HAVE_IOSTREAM +#include +#else +#include +#endif + +#ifdef HAVE_ITERATOR +#include +#else +#include +#endif + +#if HAVE_STDEXCEPT +#include +#elif HAVE_STDEXCEPT_H +#include +#endif + +#ifndef JANUS_STLPORT +#ifdef HAVE_CMATH +#include +#else +#include +#endif +#else /* JANUS_STLPORT */ +#include +#endif /* JANUS_STLPORT */ + +#else /*HAVE_CONFIG_H is not defined*/ + +#include +#include +#include + +#if defined(SGI) || defined(SGI64) || defined(SGI32) || defined(CPLANT) || defined (TFLOP) + +#include +#include +#include + +#else + +#include +#include +#include + +#endif + +#include +#include +#include +#include +#include + +#endif /*HAVE_CONFIG_H*/ + +/* Define some macros */ +#define ANASAZI_MAX(x,y) (( (x) > (y) ) ? (x) : (y) ) /* max function */ +#define ANASAZI_MIN(x,y) (( (x) < (y) ) ? (x) : (y) ) /* min function */ +#define ANASAZI_SGN(x) (( (x) < 0.0 ) ? -1.0 : 1.0 ) /* sign function */ + +/* + * Anasazi_Version() method + */ +namespace Anasazi { + std::string Anasazi_Version(); +} + +#endif /*ANASAZI_CONFIGDEFS_HPP*/ diff --git a/fastlib/trilinos/include/AnasaziEigenproblem.hpp b/fastlib/trilinos/include/AnasaziEigenproblem.hpp new file mode 100644 index 0000000000..f3bacdb051 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziEigenproblem.hpp @@ -0,0 +1,178 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_EIGENPROBLEM_H +#define ANASAZI_EIGENPROBLEM_H + +/*! \file AnasaziEigenproblem.hpp + \brief Abstract base class which defines the interface required by an eigensolver and + status test class to compute solutions to an eigenproblem +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" +#include "Teuchos_RCP.hpp" + + +/*! \class Anasazi::Eigenproblem + \brief This class defines the interface required by an eigensolver and status + test class to compute solutions to an eigenproblem. +*/ + +namespace Anasazi { + + template + class Eigenproblem { + + public: + + //! @name Constructors/Destructor + //@{ + + //! Empty constructor + Eigenproblem() {}; + + //! Destructor. + virtual ~Eigenproblem() {}; + //@} + + //! @name Set Methods + //@{ + + /*! \brief Set the operator for which eigenvalues will be computed. + * + * \note This may be different from the \c A if a spectral transformation + * is employed. For example, this operator may apply the operation + * \f$(A-\sigma I)^{-1}\f$ if you are looking for eigenvalues of \c A + * around \f$\sigma\f$. + */ + virtual void setOperator( const Teuchos::RCP &Op ) = 0; + + //! \brief Set the operator \c A of the eigenvalue problem \f$Ax=\lambda Mx\f$. + virtual void setA( const Teuchos::RCP &A ) = 0; + + //! \brief Set the operator \c M of the eigenvalue problem \f$Ax=\lambda Mx\f$. + virtual void setM( const Teuchos::RCP &M ) = 0; + + //! \brief Set the preconditioner for this eigenvalue problem \f$Ax=\lambda Mx\f$. + virtual void setPrec( const Teuchos::RCP &Prec ) = 0; + + /*! \brief Set the initial guess. + * + * \note This multivector should have the same number of columns as the blocksize. + */ + virtual void setInitVec( const Teuchos::RCP &InitVec ) = 0; + + /*! \brief Set auxiliary vectors. + * + * \note This multivector can have any number of columns, and most likely + * will contain vectors that will be used by the eigensolver to + * orthogonalize against. + */ + virtual void setAuxVecs( const Teuchos::RCP &AuxVecs ) = 0; + + //! The number of eigenvalues (NEV) that are requested. + virtual void setNEV( int nev ) = 0; + + /*! \brief Specify the symmetry of the eigenproblem. + * + * This knowledge may allow the solver to take advantage of the eigenproblems' symmetry. + * Some computational work may be avoided by setting this properly. + */ + virtual void setHermitian( bool isSym ) = 0; + + /*! \brief Specify that this eigenproblem is fully defined. + * + * This routine serves multiple purpose: + *
      + *
    • sanity check that the eigenproblem has been fully and consistently defined + *
    • opportunity for the eigenproblem to allocate internal storage for eigenvalues + * and eigenvectors (to be used by eigensolvers and solver managers) + *
    + * + * \note The user MUST call this routine before they send the eigenproblem to any solver or solver manager. + * + * \returns \c true signifies success, \c false signifies error. + */ + virtual bool setProblem() = 0; + + /*! \brief Set the solution to the eigenproblem. + * + * This mechanism allows an Eigensolution struct to be associated with an Eigenproblem object. + * setSolution() is usually called by a solver manager at the end of its SolverManager::solve() + * routine. + */ + virtual void setSolution(const Eigensolution &sol) = 0; + + //@} + + //! @name Accessor Methods + //@{ + + //! Get a pointer to the operator for which eigenvalues will be computed. + virtual Teuchos::RCP getOperator() const = 0; + + //! Get a pointer to the operator \c A of the eigenproblem \f$AX=\lambda Mx\f$. + virtual Teuchos::RCP getA() const = 0; + + //! Get a pointer to the operator \c M of the eigenproblem \f$AX=\lambda Mx\f$. + virtual Teuchos::RCP getM() const = 0; + + //! Get a pointer to the preconditioner. + virtual Teuchos::RCP getPrec() const = 0; + + //! Get a pointer to the initial vector + virtual Teuchos::RCP getInitVec() const = 0; + + //! Get a pointer to the auxiliary vector + virtual Teuchos::RCP getAuxVecs() const = 0; + + //! Get the number of eigenvalues (NEV) that are required by this eigenproblem. + virtual int getNEV() const = 0; + + //! Get the symmetry information for this eigenproblem. + virtual bool isHermitian() const = 0; + + //! If the problem has been set, this method will return true. + virtual bool isProblemSet() const = 0; + + /*! \brief Get the solution to the eigenproblem. + * + * There is no computation associated with this method. It only provides a + * mechanism for associating an Eigensolution with a Eigenproblem. + */ + virtual const Eigensolution & getSolution() const = 0; + + //@} + }; + +} // end Anasazi namespace +#endif + +// end AnasaziEigenproblem.hpp diff --git a/fastlib/trilinos/include/AnasaziEigensolver.hpp b/fastlib/trilinos/include/AnasaziEigensolver.hpp new file mode 100644 index 0000000000..b7b3b9396a --- /dev/null +++ b/fastlib/trilinos/include/AnasaziEigensolver.hpp @@ -0,0 +1,184 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_EIGENSOLVER_HPP +#define ANASAZI_EIGENSOLVER_HPP + +/*! \file AnasaziEigensolver.hpp + \brief Pure virtual base class which describes the basic interface to the iterative eigensolver. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +#include "AnasaziEigensolverDecl.hpp" +#include "AnasaziStatusTestDecl.hpp" + +#include "AnasaziEigenproblem.hpp" +#include "AnasaziSortManager.hpp" +#include "AnasaziOutputManager.hpp" +#include "AnasaziOrthoManager.hpp" +#include "Teuchos_ParameterList.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_Array.hpp" + + +namespace Anasazi { + +template +class Eigensolver { + + public: + + //! @name Constructors/Destructor + //@{ + + //! Default Constructor. + Eigensolver() {}; + + //! Basic Constructor. + /*! This constructor, implemented by all Anasazi eigensolvers, takes an Anasazi::Eigenproblem, + Anasazi::SortManager, Anasazi::OutputManager, and Teuchos::ParameterList as input. These + four arguments are sufficient enough for constructing any Anasazi::Eigensolver object. + */ + Eigensolver( const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms ); + + //! Destructor. + virtual ~Eigensolver() {}; + //@} + + + //! @name Solver methods + //@{ + + /*! \brief This method performs eigensolvers iterations until the status test + indicates the need to stop or an error occurs (in which case, an exception is thrown). + */ + virtual void iterate() = 0; + + /*! \brief Initialize the solver with the initial vectors from the eigenproblem + * or random data. + */ + virtual void initialize() = 0; + + //@} + + + //! @name Status methods + //@{ + + //! \brief Get the current iteration count. + virtual int getNumIters() const = 0; + + //! \brief Reset the iteration count. + virtual void resetNumIters() = 0; + + /*! \brief Get the Ritz vectors from the previous iteration. These are indexed using getRitzIndex(). + * + * For a description of the indexing scheme, see getRitzIndex(). + */ + virtual Teuchos::RCP getRitzVectors() = 0; + + //! \brief Get the Ritz values from the previous iteration. + virtual std::vector > getRitzValues() = 0; + + /*! \brief Get the index used for indexing the compressed storage used for Ritz vectors for real, non-Hermitian problems. + * + * index has length numVecs, where each entry is 0, +1, or -1. These have the following interpretation: + * - index[i] == 0: signifies that the corresponding eigenvector is stored as the i column of Evecs. This will usually be the + * case when ScalarType is complex, an eigenproblem is Hermitian, or a real, non-Hermitian eigenproblem has a real eigenvector. + * - index[i] == +1: signifies that the corresponding eigenvector is stored in two vectors: the real part in the i column of Evecs and the positive imaginary part in the i+1 column of Evecs. + * - index[i] == -1: signifies that the corresponding eigenvector is stored in two vectors: the real part in the i-1 column of Evecs and the negative imaginary part in the i column of Evecs + */ + virtual std::vector getRitzIndex() = 0; + + //! \brief Get the current residual norms + /*! \return A vector of length blockSize containing the norms of the residuals, + according to the orthogonalization manager norm() method. + */ + virtual std::vector::magnitudeType> getResNorms() = 0; + + //! Get the current residual 2-norms + //! \return A vector of length blockSize containing the 2-norms of the residuals. + virtual std::vector::magnitudeType> getRes2Norms() = 0; + + //! Get the 2-norms of the Ritz residuals. + //! \return A vector of length blockSize containing the 2-norms of the Ritz residuals. + virtual std::vector::magnitudeType> getRitzRes2Norms() = 0; + + //! Get the dimension of the search subspace used to generate the current eigenvectors and eigenvalues. + virtual int getCurSubspaceDim() const = 0; + + //! Get the maximum dimension allocated for the search subspace. + virtual int getMaxSubspaceDim() const = 0; + + //@} + + + + //! @name Accessor methods + //@{ + + //! Get a constant reference to the eigenvalue problem. + virtual const Eigenproblem& getProblem() const = 0; + + //! Get the blocksize to be used by the iterative solver in solving this eigenproblem. + virtual int getBlockSize() const = 0; + + //! \brief Set the blocksize to be used by the iterative solver in solving this eigenproblem. + virtual void setBlockSize(int blockSize) = 0; + + //! Set the auxiliary vectors for the solver. + virtual void setAuxVecs(const Teuchos::Array > &auxvecs) = 0; + + //! Get the auxiliary vectors for the solver. + virtual Teuchos::Array > getAuxVecs() const = 0; + + //! States whether the solver has been initialized or not. + virtual bool isInitialized() const = 0; + + //@} + + //! @name Output methods + //@{ + + //! This method requests that the solver print out its current status to screen. + virtual void currentStatus(std::ostream &os) = 0; + + //@} + +}; + +} // end Anasazi namespace + +#endif /* ANASAZI_EIGENSOLVER_HPP */ diff --git a/fastlib/trilinos/include/AnasaziEigensolverDecl.hpp b/fastlib/trilinos/include/AnasaziEigensolverDecl.hpp new file mode 100644 index 0000000000..d7cfb4f088 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziEigensolverDecl.hpp @@ -0,0 +1,52 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_EIGENSOLVER_DECL_HPP +#define ANASAZI_EIGENSOLVER_DECL_HPP + +/*! \file AnasaziEigensolverDecl.hpp + \brief Forward declaration of the virtual base class Anasazi::Eigensolver. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +namespace Anasazi { + + /*! \class Eigensolver + \brief The Eigensolver is a templated virtual base class that defines the + basic interface that any eigensolver will support. + + This interface is mainly concerned with providing a set of eigensolver status method that + can be requested from any eigensolver by an StatusTest object. + */ + template + class Eigensolver; +} + +#endif diff --git a/fastlib/trilinos/include/AnasaziEpetraAdapter.hpp b/fastlib/trilinos/include/AnasaziEpetraAdapter.hpp new file mode 100644 index 0000000000..d9c7025acc --- /dev/null +++ b/fastlib/trilinos/include/AnasaziEpetraAdapter.hpp @@ -0,0 +1,800 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziEpetraAdapter.hpp + \brief Declarations of Anasazi multi-vector and operator classes using Epetra_MultiVector and Epetra_Operator classes +*/ + +#ifndef ANASAZI_EPETRA_ADAPTER_HPP +#define ANASAZI_EPETRA_ADAPTER_HPP + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "AnasaziMultiVec.hpp" +#include "AnasaziOperator.hpp" + +#include "Teuchos_SerialDenseMatrix.hpp" +#include "Epetra_MultiVector.h" +#include "Epetra_Operator.h" +#include "Epetra_Map.h" +#include "Epetra_LocalMap.h" + +namespace Anasazi { + + //! @name Epetra Adapter Exceptions + //@{ + + /** \brief EpetraMultiVecFailure is thrown when a return value from an Epetra + * call on an Epetra_MultiVector is non-zero. + */ + class EpetraMultiVecFailure : public AnasaziError {public: + EpetraMultiVecFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + /** \brief EpetraOpFailure is thrown when a return value from an Epetra + * call on an Epetra_Operator is non-zero. + */ + class EpetraOpFailure : public AnasaziError {public: + EpetraOpFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + //@} + + /////////////////////////////////////////////////////////////// + // + //--------template class AnasaziEpetraMultiVec----------------- + // + /////////////////////////////////////////////////////////////// + + /*! + \brief Basic adapter class for Anasazi::MultiVec that uses Epetra_MultiVector. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + class EpetraMultiVec : public MultiVec, public Epetra_MultiVector { + public: + //! @name Constructors/Destructors + //@{ + + //! Basic EpetraMultiVec constructor. + /*! @param Map [in] An Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + @param numvecs [in] Number of vectors in multi-vector. + + \returns Pointer to an EpetraMultiVec + */ + EpetraMultiVec(const Epetra_BlockMap& Map, const int numvecs); + + //! Copy constructor. + EpetraMultiVec(const Epetra_MultiVector & P_vec); + + //! Create multi-vector with values from two dimensional array. + /*! @param Map [in] An Epetra_LocalMap, Epetra_Map or Epetra_BlockMap + @param array [in] Pointer to an array of double precision numbers. The first vector starts at \c array, the + second at \c array+stride, and so on. This array is copied. + @param numvecs [in] Number of vectors in the multi-vector. + @param stride [in] The stride between vectors in memory of \c array. + + \returns Pointer to an EpetraMultiVec + */ + EpetraMultiVec(const Epetra_BlockMap& Map, double * array, const int numvecs, const int stride=0); + + //! Create multi-vector from list of vectors in an existing EpetraMultiVec. + /*! @param CV [in] Enumerated type set to Copy or View. + @param P_vec [in] An existing fully constructed Epetra_MultiVector. + @param index [in] A integer vector containing the indices of the vectors to copy out of \c P_vec. + + \returns Pointer to an EpetraMultiVec + */ + EpetraMultiVec(Epetra_DataAccess CV, const Epetra_MultiVector& P_vec, const std::vector& index); + + //! Destructor + virtual ~EpetraMultiVec() {}; + + //@} + + //! @name Creation methods + //@{ + + /*! \brief Creates a new empty EpetraMultiVec containing \c numvecs columns. + + \returns Pointer to an EpetraMultiVec + */ + MultiVec * Clone ( const int numvecs ) const; + + /*! \brief Creates a new EpetraMultiVec and copies contents of \c *this into + the new vector (deep copy). + + \returns Pointer to an EpetraMultiVec + */ + MultiVec * CloneCopy () const; + + /*! \brief Creates a new EpetraMultiVec and copies the selected contents of \c *this + into the new vector (deep copy). + + The copied vectors from \c *this are indicated by the \c index.size() indices in \c index. + + \returns Pointer to an EpetraMultiVec + */ + MultiVec * CloneCopy ( const std::vector& index ) const; + + /*! \brief Creates a new EpetraMultiVec that shares the selected contents of \c *this. + + The index of the \c numvecs vectors shallow copied from \c *this are indicated by the + indices given in \c index. + + \returns Pointer to an EpetraMultiVec + */ + MultiVec * CloneView ( const std::vector& index ); + + //@} + + //! @name Attribute methods + //@{ + + //! Obtain the vector length of *this. + int GetNumberVecs () const { return NumVectors(); } + + //! Obtain the number of vectors in *this. + int GetVecLength () const { return GlobalLength(); } + + //@} + + //! @name Update methods + //@{ + /*! \brief Update \c *this with \f$\alpha AB + \beta (*this)\f$. + */ + void MvTimesMatAddMv ( double alpha, const MultiVec& A, + const Teuchos::SerialDenseMatrix& B, + double beta ); + + /*! \brief Replace \c *this with \f$\alpha A + \beta B\f$. + */ + void MvAddMv ( double alpha, const MultiVec& A, + double beta, const MultiVec& B); + + /*! \brief Compute a dense matrix \c B through the matrix-matrix multiply \f$\alpha A^T(*this)\f$. + */ + void MvTransMv ( double alpha, const MultiVec& A, Teuchos::SerialDenseMatrix& B +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) const; + + /*! \brief Compute a vector \c b where the components are the individual dot-products, i.e. \f$ b[i] = A[i]^H(this[i])\f$ where \c A[i] is the i-th column of \c A. + */ + void MvDot ( const MultiVec& A, std::vector* b +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) const; + + /*! \brief Scale each element of the vectors in \c *this with \c alpha. + */ + void MvScale ( double alpha ) { + TEST_FOR_EXCEPTION( this->Scale( alpha )!=0, EpetraMultiVecFailure, + "Anasazi::EpetraMultiVec::MvScale call to Epetra_MultiVector::Scale() returned a nonzero value."); + } + + /*! \brief Scale each element of the \c i-th vector in \c *this with \c alpha[i]. + */ + void MvScale ( const std::vector& alpha ); + + //@} + //! @name Norm method + //@{ + + /*! \brief Compute the 2-norm of each individual vector of \c *this. + Upon return, \c normvec[i] holds the 2-norm of the \c i-th vector of \c *this + */ + void MvNorm ( std::vector* normvec ) const { + if ((normvec!=NULL) && ((int)normvec->size() >= GetNumberVecs()) ) { + TEST_FOR_EXCEPTION( this->Norm2(&(*normvec)[0])!=0, EpetraMultiVecFailure, + "Anasazi::EpetraMultiVec::MvNorm call to Epetra_MultiVector::Norm2() returned a nonzero value."); + } + }; + //@} + + //! @name Initialization methods + //@{ + /*! \brief Copy the vectors in \c A to a set of vectors in \c *this. + + The \c numvecs vectors in \c A are copied to a subset of vectors in \c *this + indicated by the indices given in \c index. + */ + void SetBlock ( const MultiVec& A, const std::vector& index ); + + /*! \brief Fill the vectors in \c *this with random numbers. + */ + void MvRandom() { + TEST_FOR_EXCEPTION( this->Random()!=0, EpetraMultiVecFailure, + "Anasazi::EpetraMultiVec::MvRandom call to Epetra_MultiVector::Random() returned a nonzero value."); + }; + + /*! \brief Replace each element of the vectors in \c *this with \c alpha. + */ + void MvInit ( double alpha ) { + TEST_FOR_EXCEPTION( this->PutScalar( alpha )!=0, EpetraMultiVecFailure, + "Anasazi::EpetraMultiVec::MvInit call to Epetra_MultiVector::PutScalar() returned a nonzero value."); + }; + + //@} + //! @name Print method + //@{ + /*! \brief Print \c *this EpetraMultiVec. + */ + void MvPrint( std::ostream& os ) const { os << *this << std::endl; }; + //@} + + private: + }; + //------------------------------------------------------------- + + /////////////////////////////////////////////////////////////// + // + //--------template class AnasaziEpetraOp--------------------- + // + /////////////////////////////////////////////////////////////// + + /*! + \brief Basic adapter class for Anasazi::Operator that uses Epetra_Operator. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + class EpetraOp : public virtual Operator { + public: + //! @name Constructor/Destructor + //@{ + + //! Basic constructor. Accepts reference-counted pointer to an Epetra_Operator. + EpetraOp(const Teuchos::RCP &Op ); + + //! Destructor + ~EpetraOp(); + //@} + + //! @name Operator application method + //@{ + + /*! \brief This method takes the Anasazi::MultiVec \c X and + applies the operator to it resulting in the Anasazi::MultiVec \c Y. + */ + void Apply ( const MultiVec& X, MultiVec& Y ) const; + //@} + + private: + Teuchos::RCP Epetra_Op; + }; + //------------------------------------------------------------- + + /////////////////////////////////////////////////////////////// + // + //--------template class AnasaziEpetraGenOp-------------------- + // + /////////////////////////////////////////////////////////////// + + /*! + \brief Adapter class for creating an operators often used in solving generalized eigenproblems. + + This class will apply the operation \f$A^{-1}M\f$ [default] or \f$AM\f$, for the \c Apply method of the + Epetra_Operator / Anasazi::Operator. The Anasazi::EpetraGenOp operator is useful when spectral + transformations are used within eigensolvers. For instance, \f$A^{-1}M\f$ is a shift and invert + spectral transformation commonly used with Anasazi::BlockKrylovSchur to compute the smallest-magnitude + eigenvalues for the eigenproblem \f$Ax = \lambda Mx\f$. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + + class EpetraGenOp : public virtual Operator, public virtual Epetra_Operator { + public: + //! Basic constructor for applying operator \f$A^{-1}M\f$ [default] or \f$AM\f$. + /*! If \c isAInverse is true this operator will apply \f$A^{-1}M\f$, else + it will apply \f$AM\f$. + */ + EpetraGenOp(const Teuchos::RCP &AOp, + const Teuchos::RCP &MOp, + bool isAInverse = true ); + + //! Destructor + ~EpetraGenOp(); + + //! Apply method [inherited from Anasazi::Operator class] + /*! This method will apply \f$A^{-1}M\f$ or \f$AM\f$ to \c X, returning \c Y. + */ + void Apply ( const MultiVec& X, MultiVec& Y ) const; + + //! Apply method [inherited from Epetra_Operator class] + /*! This method will apply \f$A^{-1}M\f$ or \f$AM\f$ to \c X, returning \c Y. + */ + int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const; + + //! Apply inverse method [inherited from Epetra_Operator class] + /*! This method will apply \f$(A^{-1}M)^{-1}\f$ or \f$(AM)^{-1}\f$ to \c X, returning \c Y. + */ + int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const; + + //! Returns a character string describing the operator. + const char* Label() const { return "Epetra_Operator applying A^{-1}M"; }; + + //! Returns the current UseTranspose setting [always false for this operator]. + bool UseTranspose() const { return (false); }; + + //! If set true, the transpose of this operator will be applied [not functional for this operator]. + int SetUseTranspose(bool UseTranspose) { return 0; }; + + //! Returns true if this object can provide an approximate inf-norm [always false for this operator]. + bool HasNormInf() const { return (false); }; + + //! Returns the infinity norm of the global matrix [not functional for this operator]. + double NormInf() const { return (-1.0); }; + + //! Returns the Epetra_Comm communicator associated with this operator. + const Epetra_Comm& Comm() const { return Epetra_AOp->Comm(); }; + + //! Returns the Epetra_Map object associated with the domain of this operator. + const Epetra_Map& OperatorDomainMap() const { return Epetra_AOp->OperatorDomainMap(); }; + + //! Returns the Epetra_Map object associated with the range of this operator. + const Epetra_Map& OperatorRangeMap() const { return Epetra_AOp->OperatorRangeMap(); }; + + private: + bool isAInverse; + Teuchos::RCP Epetra_AOp; + Teuchos::RCP Epetra_MOp; + }; + + /////////////////////////////////////////////////////////////// + // + //--------template class AnasaziEpetraSymOp-------------------- + // + /////////////////////////////////////////////////////////////// + + /*! + \brief Adapter class for creating a symmetric operator from an Epetra_Operator. + + This class will apply the operation \f$A^TA\f$ [default] or \f$AA^T\f$, for the \c Apply method of the + Epetra_Operator / Anasazi::Operator. The Anasazi::EpetraSymOp operator is useful when trying to compute + a few singular values of the operator \f$A\f$. The singular values are the square-root of the eigenvalues + of \f$A^TA\f$ and \f$AA^T\f$. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + + class EpetraSymOp : public virtual Operator, public virtual Epetra_Operator { + public: + //! Basic constructor for applying operator \f$A^TA\f$ [default] or \f$AA^T\f$. + /*! If \c isTrans is false this operator will apply \f$A^TA\f$, else it will apply \f$AA^T\f$. + */ + EpetraSymOp(const Teuchos::RCP &Op, bool isTrans = false ); + + //! Destructor + ~EpetraSymOp(); + + //! Apply method [inherited from Anasazi::Operator class] + /*! This method will apply \f$A^TA\f$ or \f$AA^T\f$ to \c X, returning \c Y. + */ + void Apply ( const MultiVec& X, MultiVec& Y ) const; + + //! Apply method [inherited from Epetra_Operator class] + /*! This method will apply \f$A^TA\f$ or \f$AA^T\f$ to \c X, returning \c Y. + */ + int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const; + + //! Apply inverse method [inherited from Epetra_Operator class] + /*! This method will apply \f$(A^TA)^{-1}\f$ or \f$(AA^T)^{-1}\f$ to \c X, returning \c Y. + \note This method is only defined if \f$A^{-1}\f$ is defined for the given Epetra_Operator. + */ + int ApplyInverse(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const; + + //! Returns a character string describing the operator. + const char* Label() const { return "Epetra_Operator applying A^TA or AA^T"; }; + + //! Returns the current UseTranspose setting [always false for this operator]. + bool UseTranspose() const { return (false); }; + + //! If set true, the transpose of this operator will be applied [not functional for this operator]. + int SetUseTranspose(bool UseTranspose) { return 0; }; + + //! Returns true if this object can provide an approximate inf-norm [always false for this operator]. + bool HasNormInf() const { return (false); }; + + //! Returns the infinity norm of the global matrix [not functional for this operator]. + double NormInf() const { return (-1.0); }; + + //! Returns the Epetra_Comm communicator associated with this operator. + const Epetra_Comm& Comm() const { return Epetra_Op->Comm(); }; + + //! Returns the Epetra_Map object associated with the domain of this operator. + const Epetra_Map& OperatorDomainMap() const { return Epetra_Op->OperatorDomainMap(); }; + + //! Returns the Epetra_Map object associated with the range of this operator. + const Epetra_Map& OperatorRangeMap() const { return Epetra_Op->OperatorRangeMap(); }; + + private: + Teuchos::RCP Epetra_Op; + bool isTrans_; + }; + + + ////////////////////////////////////////////////////////////////// + // + //--------template class AnasaziEpetraSymMVOp--------------------- + // + ////////////////////////////////////////////////////////////////// + + /*! + \brief Adapter class for creating a symmetric operator from an Epetra_MultiVector. + + This class will apply the operation \f$A^TA\f$ [default] or \f$AA^T\f$, for the \c Apply method of the + Epetra_Operator / Anasazi::Operator. The Anasazi::EpetraSymMvOp operator is useful when trying to compute + a few singular values of the Epetra_MultiVector \f$A\f$. The singular values are the square-root of the + eigenvalues of \f$A^TA\f$ and \f$AA^T\f$. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + + class EpetraSymMVOp : public virtual Operator { + public: + //! Basic constructor for applying operator \f$A^TA\f$ [default] or \f$AA^T\f$. + /*! If \c isTrans is false this operator will apply \f$A^TA\f$, else it will apply \f$AA^T\f$. + */ + EpetraSymMVOp(const Teuchos::RCP &MV, + bool isTrans = false ); + + //! Destructor + ~EpetraSymMVOp() {}; + + //! Apply method + /*! This method will apply \f$A^TA\f$ or \f$AA^T\f$ to \c X, returning \c Y. + */ + void Apply ( const MultiVec& X, MultiVec& Y ) const; + + private: + Teuchos::RCP Epetra_MV; + Teuchos::RCP MV_localmap; + Teuchos::RCP MV_blockmap; + bool isTrans_; + }; + + ////////////////////////////////////////////////////////////////// + // + //--------template class AnasaziEpetraWSymMVOp--------------------- + // + ////////////////////////////////////////////////////////////////// + + /*! + \brief Adapter class for creating a weighted symmetric operator from an Epetra_MultiVector and Epetra_Operator. + + This class will apply the operation \f$(WA)^T*WA\f$ for the \c Apply method of the + Anasazi::Operator. The Anasazi::EpetraWSymMvOp operator is useful when trying to compute + a few singular values of the Epetra_MultiVector \f$A\f$ under the weighting matrix \f$W\f$. + The singular values are the square-root of the eigenvalues of \f$(WA)^T*WA\f$. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + + class EpetraWSymMVOp : public virtual Operator { + public: + //! Basic constructor for applying operator \f$A^TA\f$ [default] or \f$AA^T\f$. + /*! If \c isTrans is false this operator will apply \f$A^TA\f$, else it will apply \f$AA^T\f$. + */ + EpetraWSymMVOp(const Teuchos::RCP &MV, + const Teuchos::RCP &OP ); + + //! Destructor + ~EpetraWSymMVOp() {}; + + //! Apply method + /*! This method will apply \f$(WA)^T*WA\f$ to \c X, returning \c Y. + */ + void Apply ( const MultiVec& X, MultiVec& Y ) const; + + private: + Teuchos::RCP Epetra_MV; + Teuchos::RCP Epetra_OP; + Teuchos::RCP Epetra_WMV; + Teuchos::RCP MV_localmap; + Teuchos::RCP MV_blockmap; + }; + + + + //////////////////////////////////////////////////////////////////// + // + // Implementation of the Anasazi::MultiVecTraits for Epetra::MultiVector. + // + //////////////////////////////////////////////////////////////////// + + /*! + \brief Template specialization of Anasazi::MultiVecTraits class using the Epetra_MultiVector class. + + This interface will ensure that any Epetra_MultiVector will be accepted by the Anasazi + templated solvers. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + + template<> + class MultiVecTraits + { + public: + + //! @name Creation methods + //@{ + + /*! \brief Creates a new empty Epetra_MultiVector containing \c numvecs columns. + + \return Reference-counted pointer to the new Epetra_MultiVector. + */ + static Teuchos::RCP Clone( const Epetra_MultiVector& mv, const int numvecs ) + { return Teuchos::rcp( new Epetra_MultiVector(mv.Map(), numvecs) ); } + + /*! \brief Creates a new Epetra_MultiVector and copies contents of \c mv into the new vector (deep copy). + + \return Reference-counted pointer to the new Epetra_MultiVector. + */ + static Teuchos::RCP CloneCopy( const Epetra_MultiVector& mv ) + { return Teuchos::rcp( new Epetra_MultiVector( mv ) ); } + + /*! \brief Creates a new Epetra_MultiVector and copies the selected contents of \c mv into the new vector (deep copy). + + The copied vectors from \c mv are indicated by the \c indeX.size() indices in \c index. + \return Reference-counted pointer to the new Epetra_MultiVector. + */ + static Teuchos::RCP CloneCopy( const Epetra_MultiVector& mv, const std::vector& index ) + { + std::vector& tmp_index = const_cast &>( index ); + return Teuchos::rcp( new Epetra_MultiVector(::Copy, mv, &tmp_index[0], index.size()) ); + } + + /*! \brief Creates a new Epetra_MultiVector that shares the selected contents of \c mv (shallow copy). + + The index of the \c numvecs vectors shallow copied from \c mv are indicated by the indices given in \c index. + \return Reference-counted pointer to the new Epetra_MultiVector. + */ + static Teuchos::RCP CloneView( Epetra_MultiVector& mv, const std::vector& index ) + { + std::vector& tmp_index = const_cast &>( index ); + return Teuchos::rcp( new Epetra_MultiVector(::View, mv, &tmp_index[0], index.size()) ); + } + + /*! \brief Creates a new const Epetra_MultiVector that shares the selected contents of \c mv (shallow copy). + + The index of the \c numvecs vectors shallow copied from \c mv are indicated by the indices given in \c index. + \return Reference-counted pointer to the new const Epetra_MultiVector. + */ + static Teuchos::RCP CloneView( const Epetra_MultiVector& mv, const std::vector& index ) + { + std::vector& tmp_index = const_cast &>( index ); + return Teuchos::rcp( new Epetra_MultiVector(::View, mv, &tmp_index[0], index.size()) ); + } + + //@} + + //! @name Attribute methods + //@{ + + //! Obtain the vector length of \c mv. + static int GetVecLength( const Epetra_MultiVector& mv ) + { return mv.GlobalLength(); } + + //! Obtain the number of vectors in \c mv + static int GetNumberVecs( const Epetra_MultiVector& mv ) + { return mv.NumVectors(); } + //@} + + //! @name Update methods + //@{ + + /*! \brief Update \c mv with \f$ \alpha AB + \beta mv \f$. + */ + static void MvTimesMatAddMv( double alpha, const Epetra_MultiVector& A, + const Teuchos::SerialDenseMatrix& B, + double beta, Epetra_MultiVector& mv ) + { + Epetra_LocalMap LocalMap(B.numRows(), 0, mv.Map().Comm()); + Epetra_MultiVector B_Pvec(::Copy, LocalMap, B.values(), B.stride(), B.numCols()); + + TEST_FOR_EXCEPTION( mv.Multiply( 'N', 'N', alpha, A, B_Pvec, beta )!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvNorm call to Epetra_MultiVector::Multiply() returned a nonzero value."); + } + + /*! \brief Replace \c mv with \f$\alpha A + \beta B\f$. + */ + static void MvAddMv( double alpha, const Epetra_MultiVector& A, double beta, const Epetra_MultiVector& B, Epetra_MultiVector& mv ) + { + TEST_FOR_EXCEPTION( mv.Update( alpha, A, beta, B, 0.0 )!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvAddMv call to Epetra_MultiVector::Update() returned a nonzero value."); + } + + /*! \brief Compute a dense matrix \c B through the matrix-matrix multiply \f$ \alpha A^Tmv \f$. + */ + static void MvTransMv( double alpha, const Epetra_MultiVector& A, const Epetra_MultiVector& mv, Teuchos::SerialDenseMatrix& B +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) + { + Epetra_LocalMap LocalMap(B.numRows(), 0, mv.Map().Comm()); + Epetra_MultiVector B_Pvec(::View, LocalMap, B.values(), B.stride(), B.numCols()); + + TEST_FOR_EXCEPTION( B_Pvec.Multiply( 'T', 'N', alpha, A, mv, 0.0 )!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvTransMv call to Epetra_MultiVector::Multiply() returned a nonzero value."); + } + + /*! \brief Compute a vector \c b where the components are the individual dot-products of the \c i-th columns of \c A and \c mv, i.e.\f$b[i] = A[i]^Tmv[i]\f$. + */ + static void MvDot( const Epetra_MultiVector& mv, const Epetra_MultiVector& A, std::vector* b +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) + { + TEST_FOR_EXCEPTION( mv.Dot( A, &(*b)[0] )!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvDot call to Epetra_MultiVector::Dot() returned a nonzero value."); + } + + //@} + //! @name Norm method + //@{ + + /*! \brief Compute the 2-norm of each individual vector of \c mv. + Upon return, \c normvec[i] holds the value of \f$||mv_i||_2\f$, the \c i-th column of \c mv. + */ + static void MvNorm( const Epetra_MultiVector& mv, std::vector* normvec ) + { + TEST_FOR_EXCEPTION( mv.Norm2(&(*normvec)[0])!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvNorm call to Epetra_MultiVector::Norm2() returned a nonzero value."); + } + + //@} + + //! @name Initialization methods + //@{ + /*! \brief Copy the vectors in \c A to a set of vectors in \c mv indicated by the indices given in \c index. + */ + static void SetBlock( const Epetra_MultiVector& A, const std::vector& index, Epetra_MultiVector& mv ) + { + // Extract the "numvecs" columns of mv indicated by the index vector. + int numvecs = index.size(); + std::vector& tmp_index = const_cast &>( index ); + Epetra_MultiVector temp_vec(::View, mv, &tmp_index[0], numvecs); + + if ( A.NumVectors() != numvecs ) { + std::vector index2( numvecs ); + for(int i=0; i::SetBlock call to Epetra_MultiVector::Update() returned a nonzero value."); + } + else { + TEST_FOR_EXCEPTION( temp_vec.Update( 1.0, A, 0.0, A, 0.0 )!=0, EpetraMultiVecFailure, + "MultiVecTraits::SetBlock call to Epetra_MultiVector::Update() returned a nonzero value."); + } + } + + /*! \brief Scale each element of the vectors in \c mv with \c alpha. + */ + static void MvScale ( Epetra_MultiVector& mv, double alpha ) + { + TEST_FOR_EXCEPTION( mv.Scale( alpha )!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvScale call to Epetra_MultiVector::Scale() returned a nonzero value."); + } + + /*! \brief Scale each element of the \c i-th vector in \c mv with \c alpha[i]. + */ + static void MvScale ( Epetra_MultiVector& mv, const std::vector& alpha ) + { + // Check to make sure the vector is as long as the multivector has columns. + int numvecs = mv.NumVectors(); + TEST_FOR_EXCEPTION( (int)alpha.size() != numvecs, std::invalid_argument, + "MultiVecTraits::MvScale(MV mv,vector alpha) alpha argument size was inconsistent with number of vectors in mv.") + + std::vector tmp_index( 1, 0 ); + for (int i=0; i::MvScale call to Epetra_MultiVector::Scale() returned a nonzero value."); + tmp_index[0]++; + } + } + + /*! \brief Replace the vectors in \c mv with random vectors. + */ + static void MvRandom( Epetra_MultiVector& mv ) + { + TEST_FOR_EXCEPTION( mv.Random()!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvRandom call to Epetra_MultiVector::Random() returned a nonzero value."); + } + + /*! \brief Replace each element of the vectors in \c mv with \c alpha. + */ + static void MvInit( Epetra_MultiVector& mv, double alpha = Teuchos::ScalarTraits::zero() ) + { + TEST_FOR_EXCEPTION( mv.PutScalar(alpha)!=0, EpetraMultiVecFailure, + "MultiVecTraits::MvInit call to Epetra_MultiVector::PutScalar() returned a nonzero value."); + } + + //@} + + //! @name Print method + //@{ + + /*! \brief Print the \c mv multi-vector to the \c os output stream. + */ + static void MvPrint( const Epetra_MultiVector& mv, std::ostream& os ) + { os << mv << std::endl; } + + //@} + }; + + //////////////////////////////////////////////////////////////////// + // + // Implementation of the Anasazi::OperatorTraits for Epetra::Operator. + // + //////////////////////////////////////////////////////////////////// + + /*! + \brief Template specialization of Anasazi::OperatorTraits class using the Epetra_Operator virtual base class and + Epetra_MultiVector class. + + This interface will ensure that any Epetra_Operator and Epetra_MultiVector will be accepted by the Anasazi + templated solvers. + + \note The Epetra package performs double-precision arithmetic, so the use of Epetra with Anasazi will + only provide a double-precision eigensolver. + */ + + template <> + class OperatorTraits < double, Epetra_MultiVector, Epetra_Operator > + { + public: + + /*! \brief This method takes the Epetra_MultiVector \c x and + applies the Epetra_Operator \c Op to it resulting in the Epetra_MultiVector \c y. + */ + static void Apply ( const Epetra_Operator& Op, + const Epetra_MultiVector& x, + Epetra_MultiVector& y ) + { + TEST_FOR_EXCEPTION( Op.Apply( x, y ) != 0, OperatorError, "Error in Epetra_Operator::Apply()!" ); + } + + }; + +} // end of Anasazi namespace + +#endif +// end of file ANASAZI_EPETRA_ADAPTER_HPP diff --git a/fastlib/trilinos/include/AnasaziLOBPCG.hpp b/fastlib/trilinos/include/AnasaziLOBPCG.hpp new file mode 100644 index 0000000000..aff53042dc --- /dev/null +++ b/fastlib/trilinos/include/AnasaziLOBPCG.hpp @@ -0,0 +1,2236 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +/*! \file AnasaziLOBPCG.hpp + \brief Implementation of the locally-optimal block preconditioned conjugate gradient (LOBPCG) method +*/ + +/* + LOBPCG contains local storage of up to 10*blockSize_ vectors, representing 10 entities + X,H,P,R + KX,KH,KP (product of K and the above) + MX,MH,MP (product of M and the above, not allocated if we don't have an M matrix) + If full orthogonalization is enabled, one extra multivector of blockSize_ vectors is required to + compute the local update of X and P. + + A solver is bound to an eigenproblem at declaration. + Other solver parameters (e.g., block size, auxiliary vectors) can be changed dynamically. + + The orthogonalization manager is used to project away from the auxiliary vectors. + If full orthogonalization is enabled, the orthogonalization manager is also used to construct an M orthonormal basis. + The orthogonalization manager is subclass of MatOrthoManager, which LOBPCG assumes to be defined by the M inner product. + LOBPCG will not work correctly if the orthomanager uses a different inner product. + */ + + +#ifndef ANASAZI_LOBPCG_HPP +#define ANASAZI_LOBPCG_HPP + +#include "AnasaziTypes.hpp" + +#include "AnasaziEigensolver.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "Teuchos_ScalarTraits.hpp" + +#include "AnasaziMatOrthoManager.hpp" +#include "AnasaziSolverUtils.hpp" + +#include "Teuchos_LAPACK.hpp" +#include "Teuchos_BLAS.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" +#include "Teuchos_ParameterList.hpp" +#include "Teuchos_TimeMonitor.hpp" + +/*! \class Anasazi::LOBPCG + + \brief This class provides the Locally Optimal Block Preconditioned Conjugate Gradient (%LOBPCG) iteration, a preconditioned iteration for solving linear Hermitian eigenproblems. + + This implementation is a modification of the one found in + A. Knyazev, "Toward the optimal preconditioned eigensolver: + Locally optimal block preconditioner conjugate gradient method", + SIAM J. Sci. Comput., vol 23, n 2, pp. 517-541. + + The modification consists of the orthogonalization steps recommended in + U. Hetmaniuk and R. Lehoucq, "Basis Selection in LOBPCG", Journal of Computational Physics. + + These modifcation are referred to as full orthogonalization, and consist of also conducting + the local optimization using an orthonormal basis. + + \ingroup anasazi_solver_framework + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, Heidi Thornquist +*/ + +namespace Anasazi { + + //! @name LOBPCG Structures + //@{ + + /** \brief Structure to contain pointers to Anasazi state variables. + * + * This struct is utilized by LOBPCG::initialize() and LOBPCG::getState(). + */ + template + struct LOBPCGState { + //! The current test basis. + Teuchos::RCP V; + //! The image of the current test basis under K. + Teuchos::RCP KV; + //! The image of the current test basis under M, or Teuchos::null if M was not specified. + Teuchos::RCP MV; + + //! The current eigenvectors. + Teuchos::RCP X; + //! The image of the current eigenvectors under K. + Teuchos::RCP KX; + //! The image of the current eigenvectors under M, or Teuchos::null if M was not specified. + Teuchos::RCP MX; + + //! The current search direction. + Teuchos::RCP P; + //! The image of the current search direction under K. + Teuchos::RCP KP; + //! The image of the current search direction under M, or Teuchos::null if M was not specified. + Teuchos::RCP MP; + + /*! \brief The current preconditioned residual vectors. + * + * H is only useful when LOBPCG::iterate() throw a LOBPCGRitzFailure exception. + */ + Teuchos::RCP H; + //! The image of the current preconditioned residual vectors under K. + Teuchos::RCP KH; + //! The image of the current preconditioned residual vectors under M, or Teuchos::null if M was not specified. + Teuchos::RCP MH; + + //! The current residual vectors. + Teuchos::RCP R; + + //! The current Ritz values. + Teuchos::RCP::magnitudeType> > T; + + LOBPCGState() : + V(Teuchos::null),KV(Teuchos::null),MV(Teuchos::null), + X(Teuchos::null),KX(Teuchos::null),MX(Teuchos::null), + P(Teuchos::null),KP(Teuchos::null),MP(Teuchos::null), + H(Teuchos::null),KH(Teuchos::null),MH(Teuchos::null), + R(Teuchos::null),T(Teuchos::null) {}; + }; + + //@} + + //! @name LOBPCG Exceptions + //@{ + + /** \brief LOBPCGRitzFailure is thrown when the LOBPCG solver is unable to + * continue a call to LOBPCG::iterate() due to a failure of the algorithm. + * + * This signals that the Rayleigh-Ritz analysis over the subspace \c + * colsp([X H P]) detected ill-conditioning of the projected mass matrix + * and the inability to generate a set of orthogonal eigenvectors for + * the projected problem. + * + * This exception is only thrown from the LOBPCG::iterate() routine. After + * catching this exception, the user can recover the subspace via + * LOBPCG::getState(). This information can be used to restart the solver. + * + */ + class LOBPCGRitzFailure : public AnasaziError {public: + LOBPCGRitzFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + /** \brief LOBPCGInitFailure is thrown when the LOBPCG solver is unable to + * generate an initial iterate in the LOBPCG::initialize() routine. + * + * This exception is thrown from the LOBPCG::initialize() method, which is + * called by the user or from the LOBPCG::iterate() method when isInitialized() + * == \c false. + * + * In the case that this exception is thrown, LOBPCG::hasP() and + * LOBPCG::isInitialized() will be \c false and the user will need to provide + * a new initial iterate to the solver. + * + */ + class LOBPCGInitFailure : public AnasaziError {public: + LOBPCGInitFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + /** \brief LOBPCGOrthoFailure is thrown when an orthogonalization attempt + * fails. + * + * This is thrown in one of two scenarstd::ios. After preconditioning the residual, + * the orthogonalization manager is asked to orthogonalize the preconditioned + * residual (H) against the auxiliary vectors. If full orthogonalization + * is enabled, H is also orthogonalized against X and P and normalized. + * + * The second scenario involves the generation of new X and P from the + * basis [X H P]. When full orthogonalization is enabled, an attempt is + * made to select coefficients for X and P so that they will be + * mutually orthogonal and orthonormal. + * + * If either of these attempts fail, the solver throws an LOBPCGOrthoFailure + * exception. + */ + class LOBPCGOrthoFailure : public AnasaziError {public: + LOBPCGOrthoFailure(const std::string& what_arg) : AnasaziError(what_arg) + {}}; + + //@} + + + template + class LOBPCG : public Eigensolver { + public: + + //! @name Constructor/Destructor + //@{ + + /*! \brief %LOBPCG constructor with eigenproblem, solver utilities, and parameter list of solver options. + * + * This constructor takes pointers required by the eigensolver, in addition + * to a parameter list of options for the eigensolver. These options include the following: + * - "Block Size" - an \c int specifying the block size used by the algorithm. This can also be specified using the setBlockSize() method. + * - "Full Ortho" - a \c bool specifying whether the solver should employ a full orthogonalization technique. This can also be specified using the setFullOrtho() method. + */ + LOBPCG( const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms + ); + + //! %LOBPCG destructor + virtual ~LOBPCG() {}; + + //@} + + //! @name Solver methods + //@{ + + /*! \brief This method performs %LOBPCG iterations until the status test + * indicates the need to stop or an error occurs (in which case, an + * exception is thrown). + * + * iterate() will first determine whether the solver is initialized; if + * not, it will call initialize() using default arguments. After + * initialization, the solver performs %LOBPCG iterations until the status + * test evaluates as Passed, at which point the method returns to the + * caller. + * + * The %LOBPCG iteration proceeds as follows: + * -# The current residual (R) is preconditioned to form H + * -# H is orthogonalized against the auxiliary vectors and, if full orthogonalization\n + * is enabled, against X and P. + * -# The basis [X H P] is used to project the problem matrices. + * -# The projected eigenproblem is solved, and the desired eigenvectors and eigenvalues are selected. + * -# These are used to form the new eigenvector estimates (X) and the search directions (P).\n + * If full orthogonalization is enabled, these are generated to be mutually orthogonal and with orthonormal columns. + * -# The new residual (R) is formed. + * + * The status test is queried at the beginning of the iteration. + * + * Possible exceptions thrown include std::logic_error, std::invalid_argument or + * one of the LOBPCG-specific exceptions. + * + */ + void iterate(); + + /*! \brief Initialize the solver to an iterate, optionally providing the + * Ritz values, residual, and search direction. + * + * \note LOBPCGState contains fields V, KV and MV: These are ignored by initialize() + * + * The %LOBPCG eigensolver contains a certain amount of state relating to + * the current iterate, including the current residual, the current search + * direction, and the images of these spaces under the eigenproblem operators. + * + * initialize() gives the user the opportunity to manually set these, + * although this must be done with caution, abiding by the rules + * given below. All notions of orthogonality and orthonormality are derived + * from the inner product specified by the orthogonalization manager. + * + * \post + * - isInitialized() == true (see post-conditions of isInitialize()) + * - If newstate.P != Teuchos::null, hasP() == true.\n + * Otherwise, hasP() == false + * + * The user has the option of specifying any component of the state using + * initialize(). However, these arguments are assumed to match the + * post-conditions specified under isInitialized(). Any component of the + * state (i.e., KX) not given to initialize() will be generated. + * + */ + void initialize(LOBPCGState newstate); + + /*! \brief Initialize the solver with the initial vectors from the eigenproblem + * or random data. + */ + void initialize(); + + /*! \brief Indicates whether the solver has been initialized or not. + * + * \return bool indicating the state of the solver. + * \post + * If isInitialized() == \c true: + * - X is orthogonal to auxiliary vectors and has orthonormal columns + * - KX == Op*X + * - MX == M*X if M != Teuchos::null\n + * Otherwise, MX == Teuchos::null + * - getRitzValues() returns the sorted Ritz values with respect to X + * - getResNorms(), getRes2Norms(), getRitzResNorms() are correct + * - If hasP() == \c true, + * - P orthogonal to auxiliary vectors + * - If getFullOrtho() == \c true, + * - P is orthogonal to X and has orthonormal columns + * - KP == Op*P + * - MP == M*P if M != Teuchos::null\n + * Otherwise, MP == Teuchos::null + */ + bool isInitialized() const; + + /*! \brief Get the current state of the eigensolver. + * + * The data is only valid if isInitialized() == \c true. The + * data for the search directions P is only meaningful if hasP() == \c + * true. Finally, the data for the preconditioned residual (H) is only meaningful in the situation where + * the solver throws an ::LOBPCGRitzFailure exception during iterate(). + * + * \returns An LOBPCGState object containing const views to the current + * solver state. + */ + LOBPCGState getState() const; + + //@} + + //! @name Status methods + //@{ + + //! \brief Get the current iteration count. + int getNumIters() const; + + //! \brief Reset the iteration count. + void resetNumIters(); + + /*! \brief Get the Ritz vectors from the previous iteration. + + \return A multivector with getBlockSize() vectors containing + the sorted Ritz vectors corresponding to the most significant Ritz values. + The i-th vector of the return corresponds to the i-th Ritz vector; there is no need to use + getRitzIndex(). + */ + Teuchos::RCP getRitzVectors(); + + /*! \brief Get the Ritz values from the previous iteration. + * + * \return A vector of length getCurSubspaceDim() containing the Ritz values from the + * previous projected eigensolve. + */ + std::vector > getRitzValues(); + + /*! \brief Get the index used for extracting Ritz vectors from getRitzVectors(). + * + * Because BlockDavidson is a Hermitian solver, all Ritz values are real and all Ritz vectors can be represented in a + * single column of a multivector. Therefore, getRitzIndex() is not needed when using the output from getRitzVectors(). + * + * \return An \c int vector of size getCurSubspaceDim() composed of zeros. + */ + std::vector getRitzIndex(); + + + /*! \brief Get the current residual norms + * + * \return A vector of length getBlockSize() containing the norms of the + * residuals, with respect to the orthogonalization manager norm() method. + */ + std::vector::magnitudeType> getResNorms(); + + + /*! \brief Get the current residual 2-norms + * + * \return A vector of length getBlockSize() containing the 2-norms of the + * residuals. + */ + std::vector::magnitudeType> getRes2Norms(); + + + /*! \brief Get the 2-norms of the residuals. + * + * The Ritz residuals are not defined for the %LOBPCG iteration. Hence, this method returns the + * 2-norms of the direct residuals, and is equivalent to calling getRes2Norms(). + * + * \return A vector of length getBlockSize() containing the 2-norms of the direct residuals. + */ + std::vector::magnitudeType> getRitzRes2Norms(); + + + /*! \brief Get the dimension of the search subspace used to generate the current eigenvectors and eigenvalues. + * + * %LOBPCG employs a sequential subspace iteration, maintaining a fixed-rank basis, as opposed to an expanding subspace + * mechanism employed by Krylov-subspace solvers like BlockKrylovSchur and BlockDavidson. + * + * \return An integer specifying the rank of the subspace generated by the eigensolver. If isInitialized() == \c false, + * the return is 0. Otherwise, the return will be 2*getBlockSize() or 3*getBlockSize(). + */ + int getCurSubspaceDim() const; + + /*! \brief Get the maximum dimension allocated for the search subspace. For %LOBPCG, this always returns 3*getBlockSize(), the dimension of the + * subspace colspan([X H P]). + */ + int getMaxSubspaceDim() const; + + //@} + + //! @name Accessor routines from Eigensolver + //@{ + + + //! Get a constant reference to the eigenvalue problem. + const Eigenproblem& getProblem() const; + + + /*! \brief Set the blocksize to be used by the iterative solver in solving + * this eigenproblem. + * + * If the block size is reduced, then the new iterate (and residual and + * search direction) are chosen as the subset of the current iterate + * preferred by the sort manager. Otherwise, the solver state is set to + * uninitialized. + */ + void setBlockSize(int blockSize); + + + //! Get the blocksize to be used by the iterative solver in solving this eigenproblem. + int getBlockSize() const; + + + /*! \brief Set the auxiliary vectors for the solver. + * + * Because the current iterate X and search direction P cannot be assumed + * orthogonal to the new auxiliary vectors, a call to setAuxVecs() with a + * non-empty argument will reset the solver to the uninitialized state. + * + * In order to preserve the current state, the user will need to extract + * it from the solver using getState(), orthogonalize it against the new + * auxiliary vectors, and manually reinitialize the solver using + * initialize(). + */ + void setAuxVecs(const Teuchos::Array > &auxvecs); + + //! Get the current auxiliary vectors. + Teuchos::Array > getAuxVecs() const; + + //@} + + //! @name %LOBPCG-specific accessor routines + //@{ + + /*! \brief Instruct the LOBPCG iteration to use full orthogonality. + * + * If the getFullOrtho() == \c false and isInitialized() == \c true and hasP() == \c true, then + * P will be invalidated by setting full orthogonalization to \c true. + */ + void setFullOrtho(bool fullOrtho); + + //! Determine if the LOBPCG iteration is using full orthogonality. + bool getFullOrtho() const; + + //! Indicates whether the search direction given by getState() is valid. + bool hasP(); + + //@} + + //! @name Output methods + //@{ + + //! This method requests that the solver print out its current status to screen. + void currentStatus(std::ostream &os); + + //@} + + private: + // + // + // + void setupViews(); + // + // Convenience typedefs + // + typedef SolverUtils Utils; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + typedef Teuchos::ScalarTraits SCT; + typedef typename SCT::magnitudeType MagnitudeType; + const MagnitudeType ONE; + const MagnitudeType ZERO; + const MagnitudeType NANVAL; + // + // Internal structs + // + struct CheckList { + bool checkX, checkMX, checkKX; + bool checkH, checkMH; + bool checkP, checkMP, checkKP; + bool checkR, checkQ; + CheckList() : checkX(false),checkMX(false),checkKX(false), + checkH(false),checkMH(false), + checkP(false),checkMP(false),checkKP(false), + checkR(false),checkQ(false) {}; + }; + // + // Internal methods + // + std::string accuracyCheck(const CheckList &chk, const std::string &where) const; + // + // Classes inputed through constructor that define the eigenproblem to be solved. + // + const Teuchos::RCP > problem_; + const Teuchos::RCP > sm_; + const Teuchos::RCP > om_; + const Teuchos::RCP > tester_; + const Teuchos::RCP > orthman_; + // + // Information obtained from the eigenproblem + // + Teuchos::RCP Op_; + Teuchos::RCP MOp_; + Teuchos::RCP Prec_; + bool hasM_; + // + // Internal timers + // + Teuchos::RCP timerOp_, timerMOp_, timerPrec_, + timerSort_, + timerLocalProj_, timerDS_, + timerLocalUpdate_, timerCompRes_, + timerOrtho_, timerInit_; + // + // Counters + // + // Number of operator applications + int count_ApplyOp_, count_ApplyM_, count_ApplyPrec_; + + // + // Algorithmic parameters. + // + // blockSize_ is the solver block size + int blockSize_; + // + // fullOrtho_ dictates whether the orthogonalization procedures specified by Hetmaniuk and Lehoucq should + // be activated (see citations at the top of this file) + bool fullOrtho_; + + // + // Current solver state + // + // initialized_ specifies that the basis vectors have been initialized and the iterate() routine + // is capable of running; _initialize is controlled by the initialize() member method + // For the implications of the state of initialized_, please see documentation for initialize() + bool initialized_; + // + // nevLocal_ reflects how much of the current basis is valid (0 <= nevLocal_ <= 3*blockSize_) + // this tells us how many of the values in theta_ are valid Ritz values + int nevLocal_; + // + // hasP_ tells us whether there is valid data in P (and KP,MP) + bool hasP_; + // + // State Multivecs + // V_, KV_ MV_ and R_ are primary pointers to allocated multivectors + // the rest are multivector views into V_, KV_ and MV_ + Teuchos::RCP V_, KV_, MV_, R_; + Teuchos::RCP X_, KX_, MX_, + H_, KH_, MH_, + P_, KP_, MP_; + + // + // if fullOrtho_ == true, then we must produce the following on every iteration: + // [newX newP] = [X H P] [CX;CP] + // the structure of [CX;CP] when using full orthogonalization does not allow us to + // do this in situ, and R_ does not have enough storage for newX and newP. therefore, + // we must allocate additional storage for this. + // otherwise, when not using full orthogonalization, the structure + // [newX newP] = [X H P] [CX1 0 ] + // [CX2 CP2] allows us to work using only R as work space + // [CX3 CP3] + Teuchos::RCP tmpmvec_; + // + // auxiliary vectors + Teuchos::Array > auxVecs_; + int numAuxVecs_; + // + // Number of iterations that have been performed. + int iter_; + // + // Current eigenvalues, residual norms + std::vector theta_, Rnorms_, R2norms_; + // + // are the residual norms current with the residual? + bool Rnorms_current_, R2norms_current_; + + }; + + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + template + LOBPCG::LOBPCG( + const Teuchos::RCP > &problem, + const Teuchos::RCP > &sorter, + const Teuchos::RCP > &printer, + const Teuchos::RCP > &tester, + const Teuchos::RCP > &ortho, + Teuchos::ParameterList ¶ms + ) : + ONE(Teuchos::ScalarTraits::one()), + ZERO(Teuchos::ScalarTraits::zero()), + NANVAL(Teuchos::ScalarTraits::nan()), + // problem, tools + problem_(problem), + sm_(sorter), + om_(printer), + tester_(tester), + orthman_(ortho), + // timers, counters + timerOp_(Teuchos::TimeMonitor::getNewTimer("Operation Op*x")), + timerMOp_(Teuchos::TimeMonitor::getNewTimer("Operation M*x")), + timerPrec_(Teuchos::TimeMonitor::getNewTimer("Operation Prec*x")), + timerSort_(Teuchos::TimeMonitor::getNewTimer("Sorting eigenvalues")), + timerLocalProj_(Teuchos::TimeMonitor::getNewTimer("Local projection")), + timerDS_(Teuchos::TimeMonitor::getNewTimer("Direct solve")), + timerLocalUpdate_(Teuchos::TimeMonitor::getNewTimer("Local update")), + timerCompRes_(Teuchos::TimeMonitor::getNewTimer("Computing residuals")), + timerOrtho_(Teuchos::TimeMonitor::getNewTimer("Orthogonalization")), + timerInit_(Teuchos::TimeMonitor::getNewTimer("Initialization")), + count_ApplyOp_(0), + count_ApplyM_(0), + count_ApplyPrec_(0), + // internal data + blockSize_(0), + fullOrtho_(params.get("Full Ortho", true)), + initialized_(false), + nevLocal_(0), + hasP_(false), + auxVecs_( Teuchos::Array >(0) ), + numAuxVecs_(0), + iter_(0), + Rnorms_current_(false), + R2norms_current_(false) + { + TEST_FOR_EXCEPTION(problem_ == Teuchos::null,std::invalid_argument, + "Anasazi::LOBPCG::constructor: user passed null problem pointer."); + TEST_FOR_EXCEPTION(sm_ == Teuchos::null,std::invalid_argument, + "Anasazi::LOBPCG::constructor: user passed null sort manager pointer."); + TEST_FOR_EXCEPTION(om_ == Teuchos::null,std::invalid_argument, + "Anasazi::LOBPCG::constructor: user passed null output manager pointer."); + TEST_FOR_EXCEPTION(tester_ == Teuchos::null,std::invalid_argument, + "Anasazi::LOBPCG::constructor: user passed null status test pointer."); + TEST_FOR_EXCEPTION(orthman_ == Teuchos::null,std::invalid_argument, + "Anasazi::LOBPCG::constructor: user passed null orthogonalization manager pointer."); + TEST_FOR_EXCEPTION(problem_->isProblemSet() == false, std::invalid_argument, + "Anasazi::LOBPCG::constructor: problem is not set."); + TEST_FOR_EXCEPTION(problem_->isHermitian() == false, std::invalid_argument, + "Anasazi::LOBPCG::constructor: problem is not Hermitian; LOBPCG requires Hermitian problem."); + + // get the problem operators + Op_ = problem_->getOperator(); + TEST_FOR_EXCEPTION(Op_ == Teuchos::null, std::invalid_argument, + "Anasazi::LOBPCG::constructor: problem provides no operator."); + MOp_ = problem_->getM(); + Prec_ = problem_->getPrec(); + hasM_ = (MOp_ != Teuchos::null); + + // set the block size and allocate data + int bs = params.get("Block Size", problem_->getNEV()); + setBlockSize(bs); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Set the block size and make necessary adjustments. + template + void LOBPCG::setBlockSize (int newBS) + { + // time spent here counts towards timerInit_ + Teuchos::TimeMonitor lcltimer( *timerInit_ ); + + // This routine only allocates space; it doesn't not perform any computation + // if size is decreased, take the first newBS vectors of all and leave state as is + // otherwise, grow/allocate space and set solver to unitialized + + Teuchos::RCP tmp; + // grab some Multivector to Clone + // in practice, getInitVec() should always provide this, but it is possible to use a + // Eigenproblem with nothing in getInitVec() by manually initializing with initialize(); + // in case of that strange scenario, we will try to Clone from R_ because it is smaller + // than V_, and we don't want to keep V_ around longer than necessary + if (blockSize_ > 0) { + tmp = R_; + } + else { + tmp = problem_->getInitVec(); + TEST_FOR_EXCEPTION(tmp == Teuchos::null,std::logic_error, + "Anasazi::LOBPCG::setBlockSize(): eigenproblem did not specify initial vectors to clone from."); + } + + TEST_FOR_EXCEPTION(newBS <= 0 || newBS > MVT::GetVecLength(*tmp), std::invalid_argument, "Anasazi::LOBPCG::setBlockSize(): block size must be strictly positive."); + if (newBS == blockSize_) { + // do nothing + return; + } + else if (newBS < blockSize_ && initialized_) { + // + // shrink vectors + + // release views so we can modify the bases + X_ = Teuchos::null; + KX_ = Teuchos::null; + MX_ = Teuchos::null; + H_ = Teuchos::null; + KH_ = Teuchos::null; + MH_ = Teuchos::null; + P_ = Teuchos::null; + KP_ = Teuchos::null; + MP_ = Teuchos::null; + + // make new indices vectors + std::vector newind(newBS), oldind(newBS); + for (int i=0; i newV, newMV, newKV, newR, src; + // allocate R and newV + newR = MVT::Clone(*tmp,newBS); + newV = MVT::Clone(*tmp,newBS*3); + newKV = MVT::Clone(*tmp,newBS*3); + if (hasM_) { + newMV = MVT::Clone(*tmp,newBS*3); + } + + // + // if we are initialized, we want to pull the data from V_ into newV: + // bs | bs | bs + // newV = [newX | **** |newP ] + // newKV = [newKX| **** |newKP] + // newMV = [newMX| **** |newMP] + // where + // oldbs | oldbs | oldbs + // V_ = [newX *** | ******* | newP ***] + // KV_ = [newKX *** | ******* | newKP ***] + // MV_ = [newMX *** | ******* | newMP ***] + // + // we don't care to copy the data corresponding to H + // we will not copy the M data if !hasM_, because it doesn't exist + // + + // these are shrink operations which preserve their data + theta_.resize(3*newBS); + Rnorms_.resize(newBS); + R2norms_.resize(newBS); + + // copy residual vectors: oldind,newind currently contains [0,...,newBS-1] + src = MVT::CloneView(*R_,newind); + MVT::SetBlock(*src,newind,*newR); + // free old memory and point to new memory + R_ = newR; + + // copy in order: newX newKX newMX, then newP newKP newMP + // for X: [0,bs-1] <-- [0,bs-1] + src = MVT::CloneView(*V_,oldind); + MVT::SetBlock(*src,newind,*newV); + src = MVT::CloneView(*KV_,oldind); + MVT::SetBlock(*src,newind,*newKV); + if (hasM_) { + src = MVT::CloneView(*MV_,oldind); + MVT::SetBlock(*src,newind,*newMV); + } + // for P: [2*bs, 3*bs-1] <-- [2*oldbs, 2*oldbs+bs-1] + for (int i=0; i blockSize_ or not initialized + // this is also the scenario for our initial call to setBlockSize(), in the constructor + initialized_ = false; + hasP_ = false; + + // release views + X_ = Teuchos::null; + KX_ = Teuchos::null; + MX_ = Teuchos::null; + H_ = Teuchos::null; + KH_ = Teuchos::null; + MH_ = Teuchos::null; + P_ = Teuchos::null; + KP_ = Teuchos::null; + MP_ = Teuchos::null; + + // free allocated storage + R_ = Teuchos::null; + V_ = Teuchos::null; + + // allocate scalar vectors + theta_.resize(3*newBS,NANVAL); + Rnorms_.resize(newBS,NANVAL); + R2norms_.resize(newBS,NANVAL); + + // clone multivectors off of tmp + R_ = MVT::Clone(*tmp,newBS); + V_ = MVT::Clone(*tmp,newBS*3); + KV_ = MVT::Clone(*tmp,newBS*3); + if (hasM_) { + MV_ = MVT::Clone(*tmp,newBS*3); + } + else { + MV_ = V_; + } + } + + // allocate tmp space + tmpmvec_ = Teuchos::null; + if (fullOrtho_) { + tmpmvec_ = MVT::Clone(*tmp,newBS); + } + + // set new block size + blockSize_ = newBS; + + // setup new views + setupViews(); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Setup views into V,KV,MV + template + void LOBPCG::setupViews() + { + std::vector ind(blockSize_); + + for (int i=0; i + void LOBPCG::setAuxVecs(const Teuchos::Array > &auxvecs) { + typedef typename Teuchos::Array >::iterator tarcpmv; + + // set new auxiliary vectors + auxVecs_ = auxvecs; + + numAuxVecs_ = 0; + for (tarcpmv i=auxVecs_.begin(); i != auxVecs_.end(); i++) { + numAuxVecs_ += MVT::GetNumberVecs(**i); + } + + // If the solver has been initialized, X and P are not necessarily orthogonal to new auxiliary vectors + if (numAuxVecs_ > 0 && initialized_) { + initialized_ = false; + hasP_ = false; + } + + if (om_->isVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkQ = true; + om_->print( Debug, accuracyCheck(chk, ": in setAuxVecs()") ); + } + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + /* Initialize the state of the solver + * + * POST-CONDITIONS: + * + * initialized_ == true + * X is orthonormal, orthogonal to auxVecs_ + * KX = Op*X + * MX = M*X if hasM_ + * theta_ contains Ritz values of X + * R = KX - MX*diag(theta_) + * if hasP() == true, + * P orthogonal to auxVecs_ + * if fullOrtho_ == true, + * P orthonormal and orthogonal to X + * KP = Op*P + * MP = M*P + */ + template + void LOBPCG::initialize(LOBPCGState newstate) + { + // NOTE: memory has been allocated by setBlockSize(). Use SetBlock below; do not Clone + // NOTE: Overall time spent in this routine is counted to timerInit_; portions will also be counted towards other primitives + + Teuchos::TimeMonitor lcltimer( *timerInit_ ); + + std::vector bsind(blockSize_); + for (int i=0; i X + // --op apply-> MX,KX + // --ritz analysis-> theta + // --optional-> P,MP,KP + // + // if the user specifies all data for a level, we will accept it. + // otherwise, we will generate the whole level, and all subsequent levels. + // + // the data members are ordered based on dependence, and the levels are + // partitioned according to the amount of work required to produce the + // items in a level. + // + // inconsitent multivectors widths and lengths will not be tolerated, and + // will be treated with exceptions. + + // set up X, KX, MX: get them from "state" if user specified them + + //---------------------------------------- + // set up X, MX, KX + //---------------------------------------- + if (newstate.X != Teuchos::null) { + TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.X) != MVT::GetVecLength(*X_), + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): vector length of newstate.X not correct." ); + // newstate.X must have blockSize_ vectors; any more will be ignored + TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.X) < blockSize_, + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): newstate.X must have at least block size vectors."); + + // put X data in X_ + MVT::SetBlock(*newstate.X,bsind,*X_); + + // put MX data in MX_ + if (hasM_) { + if (newstate.MX != Teuchos::null) { + TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.MX) != MVT::GetVecLength(*MX_), + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): vector length of newstate.MX not correct." ); + // newstate.MX must have blockSize_ vectors; any more will be ignored + TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.MX) < blockSize_, + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): newstate.MX must have at least block size vectors."); + MVT::SetBlock(*newstate.MX,bsind,*MX_); + } + else { + // user didn't specify MX, compute it + { + Teuchos::TimeMonitor lcltimer( *timerMOp_ ); + OPT::Apply(*MOp_,*X_,*MX_); + count_ApplyM_ += blockSize_; + } + // we generated MX; we will generate R as well + newstate.R = Teuchos::null; + } + } + + // put data in KX + if (newstate.KX != Teuchos::null) { + TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.KX) != MVT::GetVecLength(*KX_), + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): vector length of newstate.KX not correct." ); + // newstate.KX must have blockSize_ vectors; any more will be ignored + TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.KX) < blockSize_, + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): newstate.KX must have at least block size vectors."); + MVT::SetBlock(*newstate.KX,bsind,*KX_); + } + else { + // user didn't specify KX, compute it + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*Op_,*X_,*KX_); + count_ApplyOp_ += blockSize_; + } + // we generated KX; we will generate R as well + newstate.R = Teuchos::null; + } + } + else { + // user did not specify X + // we will initialize X, compute KX and MX, and compute R + // + // clear state so we won't use any data from it below + newstate.P = Teuchos::null; + newstate.KP = Teuchos::null; + newstate.MP = Teuchos::null; + newstate.R = Teuchos::null; + newstate.T = Teuchos::null; + + // generate a basis and projectAndNormalize + Teuchos::RCP ivec = problem_->getInitVec(); + TEST_FOR_EXCEPTION(ivec == Teuchos::null,std::logic_error, + "Anasazi::LOBPCG::initialize(): Eigenproblem did not specify initial vectors to clone from."); + + int initSize = MVT::GetNumberVecs(*ivec); + if (initSize > blockSize_) { + // we need only the first blockSize_ vectors from ivec; get a view of them + initSize = blockSize_; + std::vector ind(blockSize_); + for (int i=0; i 0) { + std::vector ind(initSize); + for (int i=0; i initSize) { + std::vector ind(blockSize_ - initSize); + for (int i=0; i rX = MVT::CloneView(*X_,ind); + MVT::MvRandom(*rX); + rX = Teuchos::null; + } + + // put data in MX + if (hasM_) { + Teuchos::TimeMonitor lcltimer( *timerMOp_ ); + OPT::Apply(*MOp_,*X_,*MX_); + count_ApplyM_ += blockSize_; + } + + // remove auxVecs from X_ and normalize it + if (numAuxVecs_ > 0) { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + Teuchos::Array > > dummy; + int rank = orthman_->projectAndNormalizeMat(*X_,MX_,dummy,Teuchos::null,auxVecs_); + TEST_FOR_EXCEPTION(rank != blockSize_, LOBPCGInitFailure, + "Anasazi::LOBPCG::initialize(): Couldn't generate initial basis of full rank."); + } + else { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + int rank = orthman_->normalizeMat(*X_,MX_,Teuchos::null); + TEST_FOR_EXCEPTION(rank != blockSize_, LOBPCGInitFailure, + "Anasazi::LOBPCG::initialize(): Couldn't generate initial basis of full rank."); + } + + // put data in KX + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply(*Op_,*X_,*KX_); + count_ApplyOp_ += blockSize_; + } + } // end if (newstate.X != Teuchos::null) + + + //---------------------------------------- + // set up Ritz values + //---------------------------------------- + theta_.resize(3*blockSize_,NANVAL); + if (newstate.T != Teuchos::null) { + TEST_FOR_EXCEPTION( (signed int)(newstate.T->size()) < blockSize_, + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): newstate.T must contain at least block size Ritz values."); + for (int i=0; i KK(blockSize_,blockSize_), + MM(blockSize_,blockSize_), + S(blockSize_,blockSize_); + { + Teuchos::TimeMonitor lcltimer( *timerLocalProj_ ); + // project K + MVT::MvTransMv(ONE,*X_,*KX_,KK); + // project M + MVT::MvTransMv(ONE,*X_,*MX_,MM); + nevLocal_ = blockSize_; + } + + // solve the projected problem + { + Teuchos::TimeMonitor lcltimer( *timerDS_ ); + Utils::directSolver(blockSize_, KK, Teuchos::rcp(&MM,false), S, theta_, nevLocal_, 1); + TEST_FOR_EXCEPTION(nevLocal_ != blockSize_,LOBPCGInitFailure, + "Anasazi::LOBPCG::initialize(): Initial Ritz analysis did not produce enough Ritz pairs to initialize algorithm."); + } + + // We only have blockSize_ ritz pairs, ergo we do not need to select. + // However, we still require them to be ordered correctly + { + Teuchos::TimeMonitor lcltimer( *timerSort_ ); + + std::vector order(blockSize_); + // + // sort the first blockSize_ values in theta_ + sm_->sort( this, blockSize_, theta_, &order ); // don't catch exception + // + // apply the same ordering to the primitive ritz vectors + Utils::permuteVectors(order,S); + } + + // update the solution, use R for storage + { + Teuchos::TimeMonitor lcltimer( *timerLocalUpdate_ ); + // X <- X*S + MVT::MvAddMv( ONE, *X_, ZERO, *X_, *R_ ); + MVT::MvTimesMatAddMv( ONE, *R_, S, ZERO, *X_ ); + // KX <- KX*S + MVT::MvAddMv( ONE, *KX_, ZERO, *KX_, *R_ ); + MVT::MvTimesMatAddMv( ONE, *R_, S, ZERO, *KX_ ); + if (hasM_) { + // MX <- MX*S + MVT::MvAddMv( ONE, *MX_, ZERO, *MX_, *R_ ); + MVT::MvTimesMatAddMv( ONE, *R_, S, ZERO, *MX_ ); + } + } + } + + //---------------------------------------- + // compute R + //---------------------------------------- + if (newstate.R != Teuchos::null) { + TEST_FOR_EXCEPTION( MVT::GetVecLength(*newstate.R) != MVT::GetVecLength(*R_), + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): vector length of newstate.R not correct." ); + TEST_FOR_EXCEPTION( MVT::GetNumberVecs(*newstate.R) < blockSize_, + std::invalid_argument, "Anasazi::LOBPCG::initialize(newstate): newstate.R must have blockSize number of vectors." ); + MVT::SetBlock(*newstate.R,bsind,*R_); + } + else { + Teuchos::TimeMonitor lcltimer( *timerCompRes_ ); + // form R <- KX - MX*T + MVT::MvAddMv(ZERO,*KX_,ONE,*KX_,*R_); + Teuchos::SerialDenseMatrix T(blockSize_,blockSize_); + for (int i=0; iisVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkX = true; + chk.checkKX = true; + chk.checkMX = true; + chk.checkP = true; + chk.checkKP = true; + chk.checkMP = true; + chk.checkR = true; + chk.checkQ = true; + om_->print( Debug, accuracyCheck(chk, ": after initialize()") ); + } + + } + + template + void LOBPCG::initialize() + { + LOBPCGState empty; + initialize(empty); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Instruct the solver to use full orthogonalization + template + void LOBPCG::setFullOrtho (bool fullOrtho) + { + if ( fullOrtho_ == true || initialized_ == false || fullOrtho == fullOrtho_ ) { + // state is already orthogonalized or solver is not initialized + fullOrtho_ = fullOrtho; + } + else { + // solver is initialized, state is not fully orthogonalized, and user has requested full orthogonalization + // ergo, we must throw away data in P + fullOrtho_ = true; + hasP_ = false; + } + + // the user has called setFullOrtho, so the class has been instantiated + // ergo, the data has already been allocated, i.e., setBlockSize() has been called + // if it is already allocated, it should be the proper size + if (fullOrtho_ && tmpmvec_ == Teuchos::null) { + // allocated the workspace + tmpmvec_ = MVT::Clone(*X_,blockSize_); + } + else if (fullOrtho_==false) { + // free the workspace + tmpmvec_ = Teuchos::null; + } + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Perform LOBPCG iterations until the StatusTest tells us to stop. + template + void LOBPCG::iterate () + { + // + // Allocate/initialize data structures + // + if (initialized_ == false) { + initialize(); + } + + // + // Miscellaneous definitions + const int oneBlock = blockSize_; + const int twoBlocks = 2*blockSize_; + const int threeBlocks = 3*blockSize_; + + std::vector indblock1(blockSize_), indblock2(blockSize_), indblock3(blockSize_); + for (int i=0; i KK( threeBlocks, threeBlocks ), + MM( threeBlocks, threeBlocks ), + S( threeBlocks, threeBlocks ); + + while (tester_->checkStatus(this) != Passed) { + + // Print information on current status + if (om_->isVerbosity(Debug)) { + currentStatus( om_->stream(Debug) ); + } + else if (om_->isVerbosity(IterationDetails)) { + currentStatus( om_->stream(IterationDetails) ); + } + + // increment iteration counter + iter_++; + + // Apply the preconditioner on the residuals: H <- Prec*R + if (Prec_ != Teuchos::null) { + Teuchos::TimeMonitor lcltimer( *timerPrec_ ); + OPT::Apply( *Prec_, *R_, *H_ ); // don't catch the exception + count_ApplyPrec_ += blockSize_; + } + else { + MVT::MvAddMv(ONE,*R_,ZERO,*R_,*H_); + } + + // Apply the mass matrix on H + if (hasM_) { + Teuchos::TimeMonitor lcltimer( *timerMOp_ ); + OPT::Apply( *MOp_, *H_, *MH_); // don't catch the exception + count_ApplyM_ += blockSize_; + } + + // orthogonalize H against the auxiliary vectors + // optionally: orthogonalize H against X and P ([X P] is already orthonormal) + Teuchos::Array > Q; + Teuchos::Array > > C = + Teuchos::tuple > >(Teuchos::null); + Q = auxVecs_; + if (fullOrtho_) { + // X and P are not contiguous, so there is not much point in putting them under + // a single multivector view + Q.push_back(X_); + if (hasP_) { + Q.push_back(P_); + } + } + { + Teuchos::TimeMonitor lcltimer( *timerOrtho_ ); + int rank = orthman_->projectAndNormalizeMat(*H_,MH_,C,Teuchos::null,Q); + // our views are currently in place; it is safe to throw an exception + TEST_FOR_EXCEPTION(rank != blockSize_,LOBPCGOrthoFailure, + "Anasazi::LOBPCG::iterate(): unable to compute orthonormal basis for H."); + } + + if (om_->isVerbosity( Debug ) ) { + CheckList chk; + chk.checkH = true; + chk.checkMH = true; + om_->print( Debug, accuracyCheck(chk, ": after ortho H") ); + } + else if (om_->isVerbosity( OrthoDetails ) ) { + CheckList chk; + chk.checkH = true; + chk.checkMH = true; + om_->print( OrthoDetails, accuracyCheck(chk,": after ortho H") ); + } + + // Apply the stiffness matrix to H + { + Teuchos::TimeMonitor lcltimer( *timerOp_ ); + OPT::Apply( *Op_, *H_, *KH_); // don't catch the exception + count_ApplyOp_ += blockSize_; + } + + if (hasP_) { + nevLocal_ = threeBlocks; + } + else { + nevLocal_ = twoBlocks; + } + + // + // we need bases: [X H P] and [H P] (only need the latter if fullOrtho == false) + // we need to perform the following operations: + // X' [KX KH KP] + // X' [MX MH MP] + // H' [KH KP] + // H' [MH MP] + // P' [KP] + // P' [MP] + // [X H P] CX + // { [X H P] CP if fullOrtho + // { [H P] CP if !fullOrtho + // + // since M[X H P] is potentially the same memory as [X H P], and + // because we are not allowed to have overlapping non-const views of + // a multivector, we will now abandon our non-const views in favor of + // const views + // + X_ = Teuchos::null; + KX_ = Teuchos::null; + MX_ = Teuchos::null; + H_ = Teuchos::null; + KH_ = Teuchos::null; + MH_ = Teuchos::null; + P_ = Teuchos::null; + KP_ = Teuchos::null; + MP_ = Teuchos::null; + Teuchos::RCP cX, cH, cXHP, cHP, cK_XHP, cK_HP, cM_XHP, cM_HP, cP, cK_P, cM_P; + { + cX = MVT::CloneView(*Teuchos::rcp_implicit_cast(V_),indblock1); + cH = MVT::CloneView(*Teuchos::rcp_implicit_cast(V_),indblock2); + + std::vector indXHP(nevLocal_); + for (int i=0; i(V_),indXHP); + cK_XHP = MVT::CloneView(*Teuchos::rcp_implicit_cast(KV_),indXHP); + if (hasM_) { + cM_XHP = MVT::CloneView(*Teuchos::rcp_implicit_cast(MV_),indXHP); + } + else { + cM_XHP = cXHP; + } + + std::vector indHP(nevLocal_-blockSize_); + for (int i=blockSize_; i(V_),indHP); + cK_HP = MVT::CloneView(*Teuchos::rcp_implicit_cast(KV_),indHP); + if (hasM_) { + cM_HP = MVT::CloneView(*Teuchos::rcp_implicit_cast(MV_),indHP); + } + else { + cM_HP = cHP; + } + + if (nevLocal_ == threeBlocks) { + cP = MVT::CloneView(*Teuchos::rcp_implicit_cast(V_),indblock3); + cK_P = MVT::CloneView(*Teuchos::rcp_implicit_cast(KV_),indblock3); + if (hasM_) { + cM_P = MVT::CloneView(*Teuchos::rcp_implicit_cast(MV_),indblock3); + } + else { + cM_P = cP; + } + } + } + + // + //---------------------------------------- + // Form "local" mass and stiffness matrices + //---------------------------------------- + { + // We will form only the block upper triangular part of + // [X H P]' K [X H P] and [X H P]' M [X H P] + // Get the necessary views into KK and MM: + // [--K1--] [--M1--] + // KK = [ -K2-] MM = [ -M2-] + // [ K3] [ M3] + // + // It is okay to declare a zero-area view of a Teuchos::SerialDenseMatrix + // + Teuchos::SerialDenseMatrix + K1(Teuchos::View,KK,blockSize_,nevLocal_ ,0*blockSize_,0*blockSize_), + K2(Teuchos::View,KK,blockSize_,nevLocal_-1*blockSize_,1*blockSize_,1*blockSize_), + K3(Teuchos::View,KK,blockSize_,nevLocal_-2*blockSize_,2*blockSize_,2*blockSize_), + M1(Teuchos::View,MM,blockSize_,nevLocal_ ,0*blockSize_,0*blockSize_), + M2(Teuchos::View,MM,blockSize_,nevLocal_-1*blockSize_,1*blockSize_,1*blockSize_), + M3(Teuchos::View,MM,blockSize_,nevLocal_-2*blockSize_,2*blockSize_,2*blockSize_); + { + Teuchos::TimeMonitor lcltimer( *timerLocalProj_ ); + MVT::MvTransMv( ONE, *cX, *cK_XHP, K1 ); + MVT::MvTransMv( ONE, *cX, *cM_XHP, M1 ); + MVT::MvTransMv( ONE, *cH, *cK_HP , K2 ); + MVT::MvTransMv( ONE, *cH, *cM_HP , M2 ); + if (nevLocal_ == threeBlocks) { + MVT::MvTransMv( ONE, *cP, *cK_P, K3 ); + MVT::MvTransMv( ONE, *cP, *cM_P, M3 ); + } + } + } + // below, we only need bases [X H P] and [H P] and friends + // furthermore, we only need [H P] and friends if fullOrtho == false + // clear the others now + cX = Teuchos::null; + cH = Teuchos::null; + cP = Teuchos::null; + cK_P = Teuchos::null; + cM_P = Teuchos::null; + if (fullOrtho_ == true) { + cHP = Teuchos::null; + cK_HP = Teuchos::null; + cM_HP = Teuchos::null; + } + + // + //--------------------------------------------------- + // Perform a spectral decomposition of (KK,MM) + //--------------------------------------------------- + // + // Get pointers to relevant part of KK, MM and S for Rayleigh-Ritz analysis + Teuchos::SerialDenseMatrix lclKK(Teuchos::View,KK,nevLocal_,nevLocal_), + lclMM(Teuchos::View,MM,nevLocal_,nevLocal_), + lclS(Teuchos::View, S,nevLocal_,nevLocal_); + { + Teuchos::TimeMonitor lcltimer( *timerDS_ ); + int localSize = nevLocal_; + Utils::directSolver(localSize, lclKK, Teuchos::rcp(&lclMM,false), lclS, theta_, nevLocal_, 0); + // localSize tells directSolver() how big KK,MM are + // however, directSolver() may choose to use only the principle submatrices of KK,MM + // because of loss of MM-orthogonality in the projected eigenvectors + // nevLocal_ tells us how much it used, telling us the effective localSize + // (i.e., how much of KK,MM used by directSolver) + // we will not tolerate any indefiniteness, and will throw an exception if it was + // detected by directSolver + // + if (nevLocal_ != localSize) { + // before throwing the exception, and thereby leaving iterate(), setup the views again + // first, clear the const views + cXHP = Teuchos::null; + cK_XHP = Teuchos::null; + cM_XHP = Teuchos::null; + cHP = Teuchos::null; + cK_HP = Teuchos::null; + cM_HP = Teuchos::null; + setupViews(); + } + TEST_FOR_EXCEPTION(nevLocal_ != localSize, LOBPCGRitzFailure, + "Anasazi::LOBPCG::iterate(): indefiniteness detected in projected mass matrix." ); + } + + // + //--------------------------------------------------- + // Sort the ritz values using the sort manager + //--------------------------------------------------- + Teuchos::LAPACK lapack; + Teuchos::BLAS blas; + { + Teuchos::TimeMonitor lcltimer( *timerSort_ ); + + std::vector order(nevLocal_); + // + // Sort the first nevLocal_ values in theta_ + sm_->sort( this, nevLocal_, theta_, &order ); // don't catch exception + // + // Sort the primitive ritz vectors + Utils::permuteVectors(order,lclS); + } + + // + //---------------------------------------- + // Compute coefficients for X and P under [X H P] + //---------------------------------------- + // Before computing X,P, optionally perform orthogonalization per Hetmaniuk,Lehoucq paper + // CX will be the coefficients of [X,H,P] for new X, CP for new P + // The paper suggests orthogonalizing CP against CX and orthonormalizing CP, w.r.t. MM + // Here, we will also orthonormalize CX. + // This is accomplished using the Cholesky factorization of [CX CP]^H lclMM [CX CP] + Teuchos::RCP > CX, CP; + if (fullOrtho_) { + // build orthonormal basis for ( 0 ) that is MM orthogonal to ( S11 ) + // ( S21 ) ( S21 ) + // ( S31 ) ( S31 ) + // Do this using Cholesky factorization of ( S11 0 ) + // ( S21 S21 ) + // ( S31 S31 ) + // ( S11 0 ) + // Build C = ( S21 S21 ) + // ( S31 S31 ) + Teuchos::SerialDenseMatrix C(nevLocal_,twoBlocks), + tmp1(nevLocal_,twoBlocks), + tmp2(twoBlocks ,twoBlocks); + + // first block of rows: ( S11 0 ) + for (int j=0; j(Teuchos::Copy,C,nevLocal_,oneBlock,0,0) ); + // put C(:,oneBlock:twoBlocks-1) into CP + CP = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::Copy,C,nevLocal_,oneBlock,0,oneBlock) ); + + // check the results + if (om_->isVerbosity( Debug ) ) { + Teuchos::SerialDenseMatrix tmp1(nevLocal_,oneBlock), + tmp2(oneBlock,oneBlock); + MagnitudeType tmp; + int teuchosret; + std::stringstream os; + os.precision(2); + os.setf(std::ios::scientific, std::ios::floatfield); + + os << " Checking Full Ortho: iteration " << iter_ << std::endl; + + // check CX^T MM CX == I + // compute tmp1 = MM*CX + teuchosret = tmp1.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,lclMM,*CX,ZERO); + TEST_FOR_EXCEPTION(teuchosret != 0,std::logic_error, + "Anasazi::LOBPCG::iterate(): Logic error calling SerialDenseMatrix::multiply"); + // compute tmp2 = CX^H*tmp1 == CX^H*MM*CX + teuchosret = tmp2.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,*CX,tmp1,ZERO); + TEST_FOR_EXCEPTION(teuchosret != 0,std::logic_error, + "Anasazi::LOBPCG::iterate(): Logic error calling SerialDenseMatrix::multiply"); + // subtrace tmp2 - I == CX^H * MM * CX - I + for (int i=0; i> Error in CX^H MM CX == I : " << tmp << std::endl; + + // check CP^T MM CP == I + // compute tmp1 = MM*CP + teuchosret = tmp1.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,lclMM,*CP,ZERO); + TEST_FOR_EXCEPTION(teuchosret != 0,std::logic_error, + "Anasazi::LOBPCG::iterate(): Logic error calling SerialDenseMatrix::multiply"); + // compute tmp2 = CP^H*tmp1 == CP^H*MM*CP + teuchosret = tmp2.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,*CP,tmp1,ZERO); + TEST_FOR_EXCEPTION(teuchosret != 0,std::logic_error, + "Anasazi::LOBPCG::iterate(): Logic error calling SerialDenseMatrix::multiply"); + // subtrace tmp2 - I == CP^H * MM * CP - I + for (int i=0; i> Error in CP^H MM CP == I : " << tmp << std::endl; + + // check CX^T MM CP == 0 + // compute tmp1 = MM*CP + teuchosret = tmp1.multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,lclMM,*CP,ZERO); + TEST_FOR_EXCEPTION(teuchosret != 0,std::logic_error,"Anasazi::LOBPCG::iterate(): Logic error calling SerialDenseMatrix::multiply"); + // compute tmp2 = CX^H*tmp1 == CX^H*MM*CP + teuchosret = tmp2.multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,*CX,tmp1,ZERO); + TEST_FOR_EXCEPTION(teuchosret != 0,std::logic_error,"Anasazi::LOBPCG::iterate(): Logic error calling SerialDenseMatrix::multiply"); + // subtrace tmp2 == CX^H * MM * CP + tmp = tmp2.normFrobenius(); + os << " >> Error in CX^H MM CP == 0 : " << tmp << std::endl; + + os << std::endl; + om_->print(Debug,os.str()); + } + } + else { + // [S11 ... ...] + // S = [S21 ... ...] + // [S31 ... ...] + // + // CX = [S11] + // [S21] + // [S31] -> X = [X H P] CX + // + // CP = [S21] -> P = [H P] CP + // [S31] + // + CX = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::Copy,lclS,nevLocal_ ,oneBlock,0 ,0) ); + CP = Teuchos::rcp( new Teuchos::SerialDenseMatrix(Teuchos::Copy,lclS,nevLocal_-oneBlock,oneBlock,oneBlock,0) ); + } + + // + //---------------------------------------- + // Compute new X and new P + //---------------------------------------- + // Note: Use R as a temporary work space and (if full ortho) tmpMV as well + { + Teuchos::TimeMonitor lcltimer( *timerLocalUpdate_ ); + + // if full ortho, then CX and CP are dense + // we multiply [X H P]*CX into tmpMV + // [X H P]*CP into R + // then put V(:,firstblock) <- tmpMV + // V(:,thirdblock) <- R + // + // if no full ortho, then [H P]*CP doesn't reference first block (X) + // of V, so that we can modify it before computing P + // so we multiply [X H P]*CX into R + // V(:,firstblock) <- R + // multiply [H P]*CP into R + // V(:,thirdblock) <- R + // + // mutatis mutandis for K[XP] and M[XP] + // + // use SetBlock to do the assignments into V_ + // + // in either case, views are only allowed to be overlapping + // if they are const, and it should be assume that SetBlock + // creates a view of the associated part + // + // we have from above const-pointers to [KM]XHP, [KM]HP and (if hasP) [KM]P + // + if (fullOrtho_) { + // X,P + MVT::MvTimesMatAddMv(ONE,*cXHP,*CX,ZERO,*tmpmvec_); + MVT::MvTimesMatAddMv(ONE,*cXHP,*CP,ZERO,*R_); + cXHP = Teuchos::null; + MVT::SetBlock(*tmpmvec_,indblock1,*V_); + MVT::SetBlock(*R_ ,indblock3,*V_); + // KX,KP + MVT::MvTimesMatAddMv(ONE,*cK_XHP,*CX,ZERO,*tmpmvec_); + MVT::MvTimesMatAddMv(ONE,*cK_XHP,*CP,ZERO,*R_); + cK_XHP = Teuchos::null; + MVT::SetBlock(*tmpmvec_,indblock1,*KV_); + MVT::SetBlock(*R_ ,indblock3,*KV_); + // MX,MP + if (hasM_) { + MVT::MvTimesMatAddMv(ONE,*cM_XHP,*CX,ZERO,*tmpmvec_); + MVT::MvTimesMatAddMv(ONE,*cM_XHP,*CP,ZERO,*R_); + cM_XHP = Teuchos::null; + MVT::SetBlock(*tmpmvec_,indblock1,*MV_); + MVT::SetBlock(*R_ ,indblock3,*MV_); + } + else { + cM_XHP = Teuchos::null; + } + } + else { + // X,P + MVT::MvTimesMatAddMv(ONE,*cXHP,*CX,ZERO,*R_); + cXHP = Teuchos::null; + MVT::SetBlock(*R_,indblock1,*V_); + MVT::MvTimesMatAddMv(ONE,*cHP,*CP,ZERO,*R_); + cHP = Teuchos::null; + MVT::SetBlock(*R_,indblock3,*V_); + // KX,KP + MVT::MvTimesMatAddMv(ONE,*cK_XHP,*CX,ZERO,*R_); + cK_XHP = Teuchos::null; + MVT::SetBlock(*R_,indblock1,*KV_); + MVT::MvTimesMatAddMv(ONE,*cK_HP,*CP,ZERO,*R_); + cK_HP = Teuchos::null; + MVT::SetBlock(*R_,indblock3,*KV_); + // MX,MP + if (hasM_) { + MVT::MvTimesMatAddMv(ONE,*cM_XHP,*CX,ZERO,*R_); + cM_XHP = Teuchos::null; + MVT::SetBlock(*R_,indblock1,*MV_); + MVT::MvTimesMatAddMv(ONE,*cM_HP,*CP,ZERO,*R_); + cM_HP = Teuchos::null; + MVT::SetBlock(*R_,indblock3,*MV_); + } + else { + cM_XHP = Teuchos::null; + cM_HP = Teuchos::null; + } + } + } // end timing block + // done with coefficient matrices + CX = Teuchos::null; + CP = Teuchos::null; + + // + // we now have a P direction + hasP_ = true; + + // debugging check: all of our const views should have been cleared by now + // if not, we have a logic error above + TEST_FOR_EXCEPTION( cXHP != Teuchos::null || cK_XHP != Teuchos::null || cM_XHP != Teuchos::null + || cHP != Teuchos::null || cK_HP != Teuchos::null || cM_HP != Teuchos::null + || cP != Teuchos::null || cK_P != Teuchos::null || cM_P != Teuchos::null, + std::logic_error, + "Anasazi::BlockKrylovSchur::iterate(): const views were not all cleared! Something went wrong!" ); + + // + // recreate our const MV views of X,H,P and friends + setupViews(); + + // + // Compute the new residuals, explicitly + { + Teuchos::TimeMonitor lcltimer( *timerCompRes_ ); + MVT::MvAddMv( ONE, *KX_, ZERO, *KX_, *R_ ); + Teuchos::SerialDenseMatrix T( blockSize_, blockSize_ ); + for (int i = 0; i < blockSize_; i++) { + T(i,i) = theta_[i]; + } + MVT::MvTimesMatAddMv( -ONE, *MX_, T, ONE, *R_ ); + } + + // R has been updated; mark the norms as out-of-date + Rnorms_current_ = false; + R2norms_current_ = false; + + // When required, monitor some orthogonalities + if (om_->isVerbosity( Debug ) ) { + // Check almost everything here + CheckList chk; + chk.checkX = true; + chk.checkKX = true; + chk.checkMX = true; + chk.checkP = true; + chk.checkKP = true; + chk.checkMP = true; + chk.checkR = true; + om_->print( Debug, accuracyCheck(chk, ": after local update") ); + } + else if (om_->isVerbosity( OrthoDetails )) { + CheckList chk; + chk.checkX = true; + chk.checkP = true; + chk.checkR = true; + om_->print( OrthoDetails, accuracyCheck(chk, ": after local update") ); + } + } // end while (statusTest == false) + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // compute/return residual M-norms + template + std::vector::magnitudeType> + LOBPCG::getResNorms() { + if (Rnorms_current_ == false) { + // Update the residual norms + orthman_->norm(*R_,&Rnorms_); + Rnorms_current_ = true; + } + return Rnorms_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // compute/return residual 2-norms + template + std::vector::magnitudeType> + LOBPCG::getRes2Norms() { + if (R2norms_current_ == false) { + // Update the residual 2-norms + MVT::MvNorm(*R_,&R2norms_); + R2norms_current_ = true; + } + return R2norms_; + } + + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Check accuracy, orthogonality, and other debugging stuff + // + // bools specify which tests we want to run (instead of running more than we actually care about) + // + // we don't bother checking the following because they are computed explicitly: + // H == Prec*R + // KH == K*H + // + // + // checkX : X orthonormal + // orthogonal to auxvecs + // checkMX: check MX == M*X + // checkKX: check KX == K*X + // checkP : if fullortho P orthonormal and orthogonal to X + // orthogonal to auxvecs + // checkMP: check MP == M*P + // checkKP: check KP == K*P + // checkH : if fullortho H orthonormal and orthogonal to X and P + // orthogonal to auxvecs + // checkMH: check MH == M*H + // checkR : check R orthogonal to X + // checkQ : check that auxiliary vectors are actually orthonormal + // + // TODO: + // add checkTheta + // + template + std::string LOBPCG::accuracyCheck( const CheckList &chk, const std::string &where ) const + { + using std::endl; + + std::stringstream os; + os.precision(2); + os.setf(std::ios::scientific, std::ios::floatfield); + MagnitudeType tmp; + + os << " Debugging checks: iteration " << iter_ << where << endl; + + // X and friends + if (chk.checkX && initialized_) { + tmp = orthman_->orthonormError(*X_); + os << " >> Error in X^H M X == I : " << tmp << endl; + for (unsigned int i=0; iorthogError(*X_,*auxVecs_[i]); + os << " >> Error in X^H M Q[" << i << "] == 0 : " << tmp << endl; + } + } + if (chk.checkMX && hasM_ && initialized_) { + tmp = Utils::errorEquality(*X_, *MX_, MOp_); + os << " >> Error in MX == M*X : " << tmp << endl; + } + if (chk.checkKX && initialized_) { + tmp = Utils::errorEquality(*X_, *KX_, Op_); + os << " >> Error in KX == K*X : " << tmp << endl; + } + + // P and friends + if (chk.checkP && hasP_ && initialized_) { + if (fullOrtho_) { + tmp = orthman_->orthonormError(*P_); + os << " >> Error in P^H M P == I : " << tmp << endl; + tmp = orthman_->orthogError(*P_,*X_); + os << " >> Error in P^H M X == 0 : " << tmp << endl; + } + for (unsigned int i=0; iorthogError(*P_,*auxVecs_[i]); + os << " >> Error in P^H M Q[" << i << "] == 0 : " << tmp << endl; + } + } + if (chk.checkMP && hasM_ && hasP_ && initialized_) { + tmp = Utils::errorEquality(*P_, *MP_, MOp_); + os << " >> Error in MP == M*P : " << tmp << endl; + } + if (chk.checkKP && hasP_ && initialized_) { + tmp = Utils::errorEquality(*P_, *KP_, Op_); + os << " >> Error in KP == K*P : " << tmp << endl; + } + + // H and friends + if (chk.checkH && initialized_) { + if (fullOrtho_) { + tmp = orthman_->orthonormError(*H_); + os << " >> Error in H^H M H == I : " << tmp << endl; + tmp = orthman_->orthogError(*H_,*X_); + os << " >> Error in H^H M X == 0 : " << tmp << endl; + if (hasP_) { + tmp = orthman_->orthogError(*H_,*P_); + os << " >> Error in H^H M P == 0 : " << tmp << endl; + } + } + for (unsigned int i=0; iorthogError(*H_,*auxVecs_[i]); + os << " >> Error in H^H M Q[" << i << "] == 0 : " << tmp << endl; + } + } + if (chk.checkMH && hasM_ && initialized_) { + tmp = Utils::errorEquality(*H_, *MH_, MOp_); + os << " >> Error in MH == M*H : " << tmp << endl; + } + + // R: this is not M-orthogonality, but standard euclidean orthogonality + if (chk.checkR && initialized_) { + Teuchos::SerialDenseMatrix xTx(blockSize_,blockSize_); + MVT::MvTransMv(ONE,*X_,*R_,xTx); + tmp = xTx.normFrobenius(); + MVT::MvTransMv(ONE,*R_,*R_,xTx); + double normR = xTx.normFrobenius(); + os << " >> RelError in X^H R == 0: " << tmp/normR << endl; + } + + // Q + if (chk.checkQ) { + for (unsigned int i=0; iorthonormError(*auxVecs_[i]); + os << " >> Error in Q[" << i << "]^H M Q[" << i << "] == I : " << tmp << endl; + for (unsigned int j=i+1; jorthogError(*auxVecs_[i],*auxVecs_[j]); + os << " >> Error in Q[" << i << "]^H M Q[" << j << "] == 0 : " << tmp << endl; + } + } + } + + os << endl; + + return os.str(); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Print the current status of the solver + template + void + LOBPCG::currentStatus(std::ostream &os) + { + using std::endl; + + os.setf(std::ios::scientific, std::ios::floatfield); + os.precision(6); + os < + bool LOBPCG::isInitialized() const { + return initialized_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // is P valid or not? + template + bool LOBPCG::hasP() { + return hasP_; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // is full orthogonalization enabled or not? + template + bool LOBPCG::getFullOrtho() const { + return(fullOrtho_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current auxilliary vectors + template + Teuchos::Array > LOBPCG::getAuxVecs() const { + return auxVecs_; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current block size + template + int LOBPCG::getBlockSize() const { + return(blockSize_); + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current eigenproblem + template + const Eigenproblem& LOBPCG::getProblem() const { + return(*problem_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the max subspace dimension + template + int LOBPCG::getMaxSubspaceDim() const { + return 3*blockSize_; + } + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current subspace dimension + template + int LOBPCG::getCurSubspaceDim() const { + if (!initialized_) return 0; + return nevLocal_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current ritz residual norms + template + std::vector::magnitudeType> + LOBPCG::getRitzRes2Norms() + { + return this->getRes2Norms(); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current compression indices + template + std::vector LOBPCG::getRitzIndex() { + std::vector ret(nevLocal_,0); + return ret; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the current ritz values + template + std::vector > LOBPCG::getRitzValues() { + std::vector > ret(nevLocal_); + for (int i=0; i + Teuchos::RCP LOBPCG::getRitzVectors() { + return X_; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // reset the iteration counter + template + void LOBPCG::resetNumIters() { + iter_=0; + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the number of iterations + template + int LOBPCG::getNumIters() const { + return(iter_); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // return the state + template + LOBPCGState LOBPCG::getState() const { + LOBPCGState state; + state.V = V_; + state.KV = KV_; + state.X = X_; + state.KX = KX_; + state.P = P_; + state.KP = KP_; + state.H = H_; + state.KH = KH_; + state.R = R_; + state.T = Teuchos::rcp(new std::vector(theta_)); + if (hasM_) { + state.MV = MV_; + state.MX = MX_; + state.MP = MP_; + state.MH = MH_; + } + else { + state.MX = Teuchos::null; + state.MP = Teuchos::null; + state.MH = Teuchos::null; + } + return state; + } + +} // end Anasazi namespace + +#endif // ANASAZI_LOBPCG_HPP diff --git a/fastlib/trilinos/include/AnasaziLOBPCGSolMgr.hpp b/fastlib/trilinos/include/AnasaziLOBPCGSolMgr.hpp new file mode 100644 index 0000000000..11dbc61ce6 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziLOBPCGSolMgr.hpp @@ -0,0 +1,797 @@ + +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_LOBPCG_SOLMGR_HPP +#define ANASAZI_LOBPCG_SOLMGR_HPP + +/*! \file AnasaziLOBPCGSolMgr.hpp + * \brief The Anasazi::LOBPCGSolMgr provides a powerful solver manager for the LOBPCG eigensolver. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +#include "AnasaziEigenproblem.hpp" +#include "AnasaziSolverManager.hpp" + +#include "AnasaziSolverUtils.hpp" + +#include "AnasaziLOBPCG.hpp" +#include "AnasaziBasicSort.hpp" +#include "AnasaziSVQBOrthoManager.hpp" +#include "AnasaziStatusTestMaxIters.hpp" +#include "AnasaziStatusTestResNorm.hpp" +#include "AnasaziStatusTestOrderedResNorm.hpp" +#include "AnasaziStatusTestCombo.hpp" +#include "AnasaziStatusTestOutput.hpp" +#include "AnasaziBasicOutputManager.hpp" + + +/** \example LOBPCG/LOBPCGEpetraEx.cpp + This is an example of how to use the Anasazi::LOBPCGSolMgr solver manager to solve a standard eigenvalue problem. +*/ + +/** \example LOBPCG/LOBPCGEpetraExGen.cpp + This is an example of how to use the Anasazi::LOBPCGSolMgr solver manager to solve a generalized eigenvalue problem. +*/ + + +/*! \class Anasazi::LOBPCGSolMgr + * + * \brief The Anasazi::LOBPCGSolMgr provides a powerful and fully-featured solver manager over the LOBPCG eigensolver. + * + * This solver manager exists to provide a flexible manager over the Anasazi::LOBPCG eigensolver intended for general use. Features + * provided by this solver manager include: + * - locking of converged eigenpairs + * - global convergence on only the significant eigenpairs (instead of any eigenpairs with low residual) + * - recovery from Anasazi::LOBPCGRitzFailure when full orthogonalization is disabled + * + * These options are all driven by a list of parameters handed to the solver manager at construction. For more information, see Anasazi::LOBPCGSolMgr::LOBPCGSolMgr(). + + \ingroup anasazi_solver_framework + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, Heidi Thornquist + */ + + +namespace Anasazi { + +template +class LOBPCGSolMgr : public SolverManager { + + private: + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + typedef Teuchos::ScalarTraits SCT; + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + public: + + //! @name Constructors/Destructor + //@{ + + /*! \brief Basic constructor for LOBPCGSolMgr. + * + * This constructor accepts the Eigenproblem to be solved in addition + * to a parameter list of options for the solver manager. These options include the following: + * - \c "Which" - a \c string specifying the desired eigenvalues: SM, LM, SR or LR. Default: "SR" + * - \c "Block Size" - a \c int specifying the block size to be used by the underlying LOBPCG solver. Default: problem->getNEV() + * - \c "Full Ortho" - a \c bool specifying whether the underlying solver should employ the full orthogonalization scheme. Default: true + * - \c "Recover" - a \c bool specifying whether the solver manager should attempt to recover in the case of a LOBPCGRitzFailure when full orthogonalization is disabled. Default: true + * - \c "Maximum Iterations" - a \c int specifying the maximum number of iterations the underlying solver is allowed to perform. Default: 100 + * - \c "Verbosity" - a sum of MsgType specifying the verbosity. Default: Anasazi::Errors + * - \c "Convergence Tolerance" - a \c MagnitudeType specifying the level that residual norms must reach to decide convergence. Default: machine precision. + * - \c "Relative Convergence Tolerance" - a \c bool specifying whether residuals norms should be scaled by their eigenvalues for the purposing of deciding convergence. Default: true + * - \c "Use Locking" - a \c bool specifying whether the algorithm should employ locking of converged eigenpairs. Default: false + * - \c "Max Locked" - a \c int specifying the maximum number of eigenpairs to be locked. Default: problem->getNEV() + * - \c "Locking Quorum" - a \c int specifying the number of eigenpairs that must meet the locking criteria before locking actually occurs. Default: 1 + * - \c "Locking Tolerance" - a \c MagnitudeType specifying the level that residual norms must reach to decide locking. Default: 0.1*convergence tolerance + * - \c "Relative Locking Tolerance" - a \c bool specifying whether residuals norms should be scaled by their eigenvalues for the purposing of deciding locking. Default: true + * - \c "Init" - a LOBPCGState struct used to initialize the LOBPCG eigensolver. + */ + LOBPCGSolMgr( const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ); + + //! Destructor. + virtual ~LOBPCGSolMgr() {}; + //@} + + //! @name Accessor methods + //@{ + + const Eigenproblem& getProblem() const { + return *problem_; + } + + //@} + + //! @name Solver application methods + //@{ + + /*! \brief This method performs possibly repeated calls to the underlying eigensolver's iterate() routine + * until the problem has been solved (as decided by the solver manager) or the solver manager decides to + * quit. + * + * This method calls LOBPCG::iterate(), which will return either because a specially constructed status test evaluates to ::Passed + * or an exception is thrown. + * + * A return from LOBPCG::iterate() signifies one of the following scenarios: + * - the maximum number of iterations has been exceeded. In this scenario, the solver manager will place\n + * all converged eigenpairs into the eigenproblem and return ::Unconverged. + * - the locking conditions have been met. In this scenario, some of the current eigenpairs will be removed\n + * from the eigensolver and placed into auxiliary storage. The eigensolver will be restarted with the remaining\n + * eigenpairs and some random information to replace the removed eigenpairs. + * - global convergence has been met. In this case, the most significant NEV eigenpairs in the solver and locked storage \n + * have met the convergence criterion. (Here, NEV refers to the number of eigenpairs requested by the Eigenproblem.) \n + * In this scenario, the solver manager will return ::Converged. + * - an LOBPCGRitzFailure exception has been thrown. If full orthogonalization is enabled and recovery from this exception\n + * is requested, the solver manager will attempt to recover from this exception by gathering the current eigenvectors, \n + * preconditioned residual, and search directions from the eigensolver, orthogonormalizing the basis composed of these \n + * three, projecting the eigenproblem, and restarting the eigensolver with the solution of the project eigenproblem. Any \n + * additional failure that occurs during this recovery effort will result in the eigensolver returning ::Unconverged. + * + * \returns ::ReturnType specifying: + * - ::Converged: the eigenproblem was solved to the specification required by the solver manager. + * - ::Unconverged: the eigenproblem was not solved to the specification desired by the solver manager + */ + ReturnType solve(); + //@} + + private: + Teuchos::RCP > problem_; + + std::string whch_; + + MagnitudeType convtol_, locktol_; + int maxIters_; + bool useLocking_; + bool relconvtol_, rellocktol_; + int blockSize_; + bool fullOrtho_; + int maxLocked_; + int verbosity_; + int lockQuorum_; + bool recover_; + Teuchos::RCP > state_; +}; + + +// Constructor +template +LOBPCGSolMgr::LOBPCGSolMgr( + const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ) : + problem_(problem), + whch_("SR"), + convtol_(MT::prec()), + maxIters_(100), + useLocking_(false), + relconvtol_(true), + rellocktol_(true), + blockSize_(0), + fullOrtho_(true), + maxLocked_(0), + verbosity_(Anasazi::Errors), + lockQuorum_(1), + recover_(true) +{ + TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager."); + TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set."); + TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric."); + TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from."); + + + // which values to solve for + whch_ = pl.get("Which",whch_); + TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR",std::invalid_argument, "Invalid sorting string."); + + // convergence tolerance + convtol_ = pl.get("Convergence Tolerance",convtol_); + relconvtol_ = pl.get("Relative Convergence Tolerance",relconvtol_); + + // locking tolerance + useLocking_ = pl.get("Use Locking",useLocking_); + rellocktol_ = pl.get("Relative Locking Tolerance",rellocktol_); + // default: should be less than convtol_ + locktol_ = convtol_/10; + locktol_ = pl.get("Locking Tolerance",locktol_); + + // maximum number of iterations + maxIters_ = pl.get("Maximum Iterations",maxIters_); + + // block size: default is nev() + blockSize_ = pl.get("Block Size",problem_->getNEV()); + TEST_FOR_EXCEPTION(blockSize_ <= 0, std::invalid_argument, + "Anasazi::LOBPCGSolMgr: \"Block Size\" must be strictly positive."); + + // max locked: default is nev(), must satisfy maxLocked_ + blockSize_ >= nev + if (useLocking_) { + maxLocked_ = pl.get("Max Locked",problem_->getNEV()); + } + else { + maxLocked_ = 0; + } + if (maxLocked_ == 0) { + useLocking_ = false; + } + TEST_FOR_EXCEPTION(maxLocked_ < 0, std::invalid_argument, + "Anasazi::LOBPCGSolMgr: \"Max Locked\" must be positive."); + TEST_FOR_EXCEPTION(maxLocked_ + blockSize_ < problem_->getNEV(), + std::invalid_argument, + "Anasazi::LOBPCGSolMgr: Not enough storage space for requested number of eigenpairs."); + + if (useLocking_) { + lockQuorum_ = pl.get("Locking Quorum",lockQuorum_); + TEST_FOR_EXCEPTION(lockQuorum_ <= 0, + std::invalid_argument, + "Anasazi::LOBPCGSolMgr: \"Locking Quorum\" must be strictly positive."); + } + + // full orthogonalization: default true + fullOrtho_ = pl.get("Full Ortho",fullOrtho_); + + // verbosity level + if (pl.isParameter("Verbosity")) { + if (Teuchos::isParameterType(pl,"Verbosity")) { + verbosity_ = pl.get("Verbosity", verbosity_); + } else { + verbosity_ = (int)Teuchos::getParameter(pl,"Verbosity"); + } + } + + // recover from LOBPCGRitzFailure + recover_ = pl.get("Recover",recover_); + + // get (optionally) an initial state + if (pl.isParameter("Init")) { + state_ = Teuchos::getParameter > >(pl,"Init"); + } +} + + +// solve() +template +ReturnType +LOBPCGSolMgr::solve() { + + const int nev = problem_->getNEV(); + + + + ////////////////////////////////////////////////////////////////////////////////////// + // Sort manager + Teuchos::RCP > sorter = Teuchos::rcp( new BasicSort(whch_) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Output manager + Teuchos::RCP > printer = Teuchos::rcp( new BasicOutputManager(verbosity_) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Status tests + // + // maximum number of iterations: optional test + Teuchos::RCP > maxtest; + if (maxIters_ > 0) { + maxtest = Teuchos::rcp( new StatusTestMaxIters(maxIters_) ); + } + // convergence + Teuchos::RCP > convtest + = Teuchos::rcp( new StatusTestOrderedResNorm(sorter,convtol_,nev,StatusTestOrderedResNorm::RES_ORTH,relconvtol_) ); + // locking + Teuchos::RCP > locktest; + if (useLocking_) { + locktest = Teuchos::rcp( new StatusTestResNorm(locktol_,lockQuorum_,StatusTestResNorm::RES_ORTH,rellocktol_) ); + } + Teuchos::Array > > alltests; + // for an OR test, the order doesn't matter + alltests.push_back(convtest); + if (maxtest != Teuchos::null) alltests.push_back(maxtest); + if (locktest != Teuchos::null) alltests.push_back(locktest); + // combo: convergence || locking || max iters + Teuchos::RCP > combotest + = Teuchos::rcp( new StatusTestCombo( StatusTestCombo::OR, alltests) ); + // printing StatusTest + Teuchos::RCP > outputtest; + if ( printer->isVerbosity(Debug) ) { + outputtest = Teuchos::rcp( new StatusTestOutput( printer,combotest,1,Passed+Failed+Undefined ) ); + } + else { + outputtest = Teuchos::rcp( new StatusTestOutput( printer,combotest,1,Passed ) ); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // Orthomanager + Teuchos::RCP > ortho + = Teuchos::rcp( new SVQBOrthoManager(problem_->getM()) ); + + ////////////////////////////////////////////////////////////////////////////////////// + // Parameter list + Teuchos::ParameterList plist; + plist.set("Block Size",blockSize_); + plist.set("Full Ortho",fullOrtho_); + + // utils + SolverUtils msutils; + + ////////////////////////////////////////////////////////////////////////////////////// + // LOBPCG solver + Teuchos::RCP > lobpcg_solver + = Teuchos::rcp( new LOBPCG(problem_,sorter,printer,outputtest,ortho,plist) ); + // set any auxiliary vectors defined in the problem + Teuchos::RCP< const MV > probauxvecs = problem_->getAuxVecs(); + if (probauxvecs != Teuchos::null) { + lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP >(probauxvecs) ); + } + + ////////////////////////////////////////////////////////////////////////////////////// + // Storage + // + // lockvecs will contain eigenvectors that have been determined "locked" by the status test + int numlocked = 0; + Teuchos::RCP lockvecs; + if (useLocking_) { + lockvecs = MVT::Clone(*problem_->getInitVec(),maxLocked_); + } + std::vector lockvals; + // workMV will be used as work space for LOBPCGRitzFailure recovery and locking + // it will be partitioned in these cases as follows: + // for LOBPCGRitzFailure recovery: + // workMV = [X H P OpX OpH OpP], where OpX OpH OpP will be used for K and M + // total size: 2*3*blocksize + // for locking + // workMV = [X P MX MP], with MX,MP needing storage only if hasM==true + // total size: 2*blocksize or 4*blocksize + Teuchos::RCP workMV; + if (fullOrtho_ == false && recover_ == true) { + workMV = MVT::Clone(*problem_->getInitVec(),2*3*blockSize_); + } + else if (useLocking_) { + if (problem_->getM() != Teuchos::null) { + workMV = MVT::Clone(*problem_->getInitVec(),4*blockSize_); + } + else { + workMV = MVT::Clone(*problem_->getInitVec(),2*blockSize_); + } + } + + // initialize the solution to nothing in case we throw an exception + Eigensolution sol; + sol.numVecs = 0; + problem_->setSolution(sol); + + // initialize the solver if the user specified a state + if (state_ != Teuchos::null) { + lobpcg_solver->initialize(*state_); + } + + // tell the lobpcg_solver to iterate + while (1) { + try { + lobpcg_solver->iterate(); + + // check convergence first + if (convtest->getStatus() == Passed || (maxtest != Teuchos::null && maxtest->getStatus() == Passed) ) { + // we have convergence or not + // convtest->whichVecs() tells us which vectors from lockvecs and solver->getRitzVectors() are the ones we want + // convtest->howMany() will tell us how many + break; + } + // check locking if we didn't converge + else if (locktest != Teuchos::null && locktest->getStatus() == Passed) { + + // remove the locked vectors,values from lobpcg_solver: put them in newvecs, newvals + int numnew = locktest->howMany(); + TEST_FOR_EXCEPTION(numnew <= 0,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): status test mistake."); + // get the indices + std::vector indnew = locktest->whichVecs(); + + // don't lock more than maxLocked_; we didn't allocate enough space. + if (numlocked + numnew > maxLocked_) { + numnew = maxLocked_ - numlocked; + indnew.resize(numnew); + } + + // the call below to lobpcg_solver->setAuxVecs() will reset the solver to unitialized with hasP() == false + // store the hasP() state for use below + bool hadP = lobpcg_solver->hasP(); + + { + // debug printing + printer->print(Debug,"Locking vectors: "); + for (unsigned int i=0; istream(Debug) << " " << indnew[i];} + printer->print(Debug,"\n"); + } + std::vector newvals(numnew); + Teuchos::RCP newvecs; + { + // work in a local scope, to hide the variabes needed for extracting this info + // get the vectors + newvecs = MVT::CloneView(*lobpcg_solver->getRitzVectors(),indnew); + // get the values + std::vector > allvals = lobpcg_solver->getRitzValues(); + for (int i=0; i indlock(numnew); + for (int i=0; i indlock(numlocked); + for (int i=0; i curlocked = MVT::CloneView(*lockvecs,indlock); + if (probauxvecs != Teuchos::null) { + lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP >(probauxvecs,curlocked) ); + } + else { + lobpcg_solver->setAuxVecs( Teuchos::tuple< Teuchos::RCP >(curlocked) ); + } + } + // add locked vals to convtest + convtest->setAuxVals(lockvals); + // fill out the empty state in the solver + { + LOBPCGState state = lobpcg_solver->getState(); + Teuchos::RCP newstateX, newstateMX, newstateP, newstateMP; + // + // workMV will be partitioned as follows: workMV = [X P MX MP], + // + // make a copy of the current X,MX state + std::vector bsind(blockSize_); + for (int i=0; i block3(blockSize_); + for (int i=0; i newX = MVT::CloneView(*newstateX,indnew); + MVT::MvRandom(*newX); + + if (newstateMX != Teuchos::null) { + Teuchos::RCP newMX = MVT::CloneView(*newstateMX,indnew); + OPT::Apply(*problem_->getM(),*newX,*newMX); + } + } + + Teuchos::Array > curauxvecs = lobpcg_solver->getAuxVecs(); + Teuchos::Array > > dummy; + // ortho X against the aux vectors + ortho->projectAndNormalizeMat(*newstateX,newstateMX,dummy,Teuchos::null,curauxvecs); + + if (hadP) { + // + // get P and optionally MP, orthogonalize against X and auxiliary vectors + std::vector block2(blockSize_); + for (int i=0; i block4(blockSize_); + for (int i=0; iprojectAndNormalizeMat(*newstateP,newstateMP,dummy,Teuchos::null,curauxvecs); + } + else { + // ortho P against the new aux vectors + ortho->projectAndNormalizeMat(*newstateP,newstateMP,dummy,Teuchos::null,curauxvecs); + } + } + // set the new state + LOBPCGState newstate; + newstate.X = newstateX; + newstate.MX = newstateMX; + newstate.P = newstateP; + newstate.MP = newstateMP; + lobpcg_solver->initialize(newstate); + } + + if (numlocked == maxLocked_) { + // disabled locking now + locktest->setQuorum(blockSize_+1); + } + } + else { + TEST_FOR_EXCEPTION(true,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): Invalid return from lobpcg_solver::iterate()."); + } + } + catch (LOBPCGRitzFailure re) { + if (fullOrtho_==true || recover_==false) { + // if we are already using full orthogonalization, there isn't much we can do here. + // the most recent information in the status tests is still valid, and can be used to extract/return the + // eigenpairs that have converged. + printer->stream(Warnings) << "Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl + << "Will not try to recover." << std::endl; + break; // while(1) + } + printer->stream(Warnings) << "Error! Caught LOBPCGRitzFailure at iteration " << lobpcg_solver->getNumIters() << std::endl + << "Full orthogonalization is off; will try to recover." << std::endl; + // get the current "basis" from the solver, orthonormalize it, do a rayleigh-ritz, and restart with the ritz vectors + // if there aren't enough, break and quit with what we have + // + // workMV = [X H P OpX OpH OpP], where OpX OpH OpP will be used for K and M + LOBPCGState curstate = lobpcg_solver->getState(); + Teuchos::RCP restart, Krestart, Mrestart; + int localsize = lobpcg_solver->hasP() ? 3*blockSize_ : 2*blockSize_; + bool hasM = problem_->getM() != Teuchos::null; + { + std::vector recind(localsize); + for (int i=0; i recind(localsize); + for (int i=0; i blk1(blockSize_); + for (int i=0; i < blockSize_; i++) blk1[i] = i; + MVT::SetBlock(*curstate.X,blk1,*restart); + + // put MX into [0 , blockSize) + if (hasM) { + MVT::SetBlock(*curstate.MX,blk1,*Mrestart); + } + } + // + // put H into [blockSize_ , 2*blockSize) + { + std::vector blk2(blockSize_); + for (int i=0; i < blockSize_; i++) blk2[i] = blockSize_+i; + MVT::SetBlock(*curstate.H,blk2,*restart); + + // put MH into [blockSize_ , 2*blockSize) + if (hasM) { + MVT::SetBlock(*curstate.MH,blk2,*Mrestart); + } + } + // optionally, put P into [2*blockSize,3*blockSize) + if (localsize == 3*blockSize_) { + std::vector blk3(blockSize_); + for (int i=0; i < blockSize_; i++) blk3[i] = 2*blockSize_+i; + MVT::SetBlock(*curstate.P,blk3,*restart); + + // put MP into [2*blockSize,3*blockSize) + if (hasM) { + MVT::SetBlock(*curstate.MP,blk3,*Mrestart); + } + } + // project against auxvecs and locked vecs, and orthonormalize the basis + Teuchos::Array > > dummy; + Teuchos::Array > Q; + { + if (numlocked > 0) { + std::vector indlock(numlocked); + for (int i=0; i curlocked = MVT::CloneView(*lockvecs,indlock); + Q.push_back(curlocked); + } + if (probauxvecs != Teuchos::null) { + Q.push_back(probauxvecs); + } + } + int rank = ortho->projectAndNormalizeMat(*restart,Mrestart,dummy,Teuchos::null,Q); + if (rank < blockSize_) { + // quit + printer->stream(Errors) << "Error! Recovered basis only rank " << rank << ". Block size is " << blockSize_ << ".\n" + << "Recovery failed." << std::endl; + break; + } + // reduce multivec size if necessary + if (rank < localsize) { + localsize = rank; + std::vector redind(localsize); + for (int i=0; i KK(localsize,localsize), MM(localsize,localsize), S(localsize,localsize); + std::vector theta(localsize); + // project the matrices + // + // MM = restart^H M restart + MVT::MvTransMv(1.0,*restart,*Mrestart,MM); + // + // compute Krestart = K*restart + OPT::Apply(*problem_->getOperator(),*restart,*Krestart); + // + // KK = restart^H K restart + MVT::MvTransMv(1.0,*restart,*Krestart,KK); + rank = localsize; + msutils.directSolver(localsize,KK,Teuchos::rcp(&MM,false),S,theta,rank,1); + if (rank < blockSize_) { + printer->stream(Errors) << "Error! Recovered basis of rank " << rank << " produced only " << rank << "ritz vectors.\n" + << "Block size is " << blockSize_ << ".\n" + << "Recovery failed." << std::endl; + break; + } + theta.resize(rank); + // + // sort the ritz values using the sort manager + { + Teuchos::BLAS blas; + std::vector order(rank); + // sort + sorter->sort( lobpcg_solver.get(), rank, theta, &order ); // don't catch exception + // Sort the primitive ritz vectors + Teuchos::SerialDenseMatrix curS(Teuchos::View,S,rank,rank); + msutils.permuteVectors(order,curS); + } + // + Teuchos::SerialDenseMatrix S1(Teuchos::View,S,localsize,blockSize_); + // + // compute the ritz vectors: store them in Krestart + LOBPCGState newstate; + Teuchos::RCP newX; + { + std::vector bsind(blockSize_); + for (int i=0; iinitialize(newstate); + } + // don't catch any other exceptions + } + + sol.numVecs = convtest->howMany(); + if (sol.numVecs > 0) { + sol.Evecs = MVT::Clone(*problem_->getInitVec(),sol.numVecs); + sol.Espace = sol.Evecs; + sol.Evals.resize(sol.numVecs); + std::vector vals(sol.numVecs); + + // copy them into the solution + std::vector which = convtest->whichVecs(); + // indices between [0,blockSize) refer to vectors/values in the solver + // indices between [blockSize,blocksize+numlocked) refer to locked vectors/values + // everything has already been ordered by the solver; we just have to partition the two references + std::vector inlocked(0), insolver(0); + for (unsigned int i=0; i= numlocked+blockSize_,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): indexing mistake."); + inlocked.push_back(which[i] - blockSize_); + } + } + + TEST_FOR_EXCEPTION(insolver.size() + inlocked.size() != (unsigned int)sol.numVecs,std::logic_error,"Anasazi::LOBPCGSolMgr::solve(): indexing mistake."); + + // set the vecs,vals in the solution + if (insolver.size() > 0) { + // set vecs + int lclnum = insolver.size(); + std::vector tosol(lclnum); + for (int i=0; i v = MVT::CloneView(*lobpcg_solver->getRitzVectors(),insolver); + MVT::SetBlock(*v,tosol,*sol.Evecs); + // set vals + std::vector > fromsolver = lobpcg_solver->getRitzValues(); + for (unsigned int i=0; i 0) { + int solnum = insolver.size(); + // set vecs + int lclnum = inlocked.size(); + std::vector tosol(lclnum); + for (int i=0; i v = MVT::CloneView(*lockvecs,inlocked); + MVT::SetBlock(*v,tosol,*sol.Evecs); + // set vals + for (unsigned int i=0; i order(sol.numVecs); + sorter->sort( lobpcg_solver.get(), sol.numVecs, vals, &order ); + // store the values in the Eigensolution + for (int i=0; icurrentStatus(printer->stream(FinalSummary)); + + // print timing information + Teuchos::TimeMonitor::summarize(printer->stream(TimingDetails)); + + problem_->setSolution(sol); + printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl; + + if (sol.numVecs < nev) return Unconverged; // return from LOBPCGSolMgr::solve() + return Converged; // return from LOBPCGSolMgr::solve() +} + + +} // end Anasazi namespace + +#endif /* ANASAZI_LOBPCG_SOLMGR_HPP */ diff --git a/fastlib/trilinos/include/AnasaziMVOPTester.hpp b/fastlib/trilinos/include/AnasaziMVOPTester.hpp new file mode 100644 index 0000000000..6a9f8546aa --- /dev/null +++ b/fastlib/trilinos/include/AnasaziMVOPTester.hpp @@ -0,0 +1,1477 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// +#ifndef ANASAZI_MVOPTESTER_HPP +#define ANASAZI_MVOPTESTER_HPP + +// Assumptions that I have made: +// * I assume/verify that a multivector must have at least one vector. This seems +// to be consistent with Epetra_MultiVec. +// * I do not assume that an operator is deterministic; I do assume that the +// operator, applied to 0, will return 0. + +/** \example MVOPTester/MVOPTesterEx.cpp + This is an example of how to use the Anasazi::TestMultiVecTraits() and Anasazi::TestOperatorTraits() methods. + */ + +/*! \file AnasaziMVOPTester.hpp + \brief Test routines for MultiVecTraits and OperatorTraits conformity. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "AnasaziOutputManager.hpp" + +#include "Teuchos_RCP.hpp" + + +namespace Anasazi { + +/*! \brief This is a function to test the correctness of a MultiVecTraits + * specialization and multivector implementation. + * + * \return Status of the test: true is success, false is error +*/ + template< class ScalarType, class MV > + bool TestMultiVecTraits( + const Teuchos::RCP > &om, + const Teuchos::RCP &A ) { + + using std::endl; + + /* MVT Contract: + + Clone(MV,int) + CloneCopy(MV) + CloneCopy(MV,vector) + USER: will request positive number of vectors + MV: will return a multivector with exactly the number of + requested vectors. + vectors are the same dimension as the cloned MV + + + CloneView(MV,vector) [const and non-const] + USER: There is no assumed communication between creation and + destruction of a view. I.e., after a view is created, changes to the + source multivector are not reflected in the view. Likewise, until + destruction of the view, changes in the view are not reflected in the + source multivector. + + GetVecLength + MV: will always be positive (MV cannot have zero vectors) + + GetNumberVecs + MV: will always be positive (MV cannot have zero vectors) + + MvAddMv + USER: multivecs will be of the same dimension and same number of vecs + MV: input vectors will not be modified + performing C=0*A+1*B will assign B to C exactly + + MvTimesMatAddMv + USER: multivecs and serialdensematrix will be of the proper shape + MV: input arguments will not be modified + following arithmetic relations hold exactly: + A*I = A + 0*B = B + 1*B = B + + MvTransMv + USER: SerialDenseMatrix will be large enough to hold results. + MV: SerialDenseMatrix will not be resized. + Inner products will satisfy |a'*b| <= |a|*|b| + alpha == 0 => SerialDenseMatrix == 0 + + MvDot + USER: Results vector will be large enough for results. + Both multivectors will have the same number of vectors. + (Epetra crashes, otherwise.) + MV: Inner products will satisfy |a'*b| <= |a|*|b| + Results vector will not be resized. + + MvNorm + MV: vector norm is always non-negative, and zero + only for zero vectors. + results vector should not be resized + + SetBlock + USER: indices will be distinct + MV: assigns copies of the vectors to the specified + locations, leaving the other vectors untouched. + + MvRandom + MV: Generate zero vector with "zero" probability + Don't gen the same vectors twice. + + MvInit + MV: Init(alpha) sets all elements to alpha + + MvPrint + MV: routine does not modify vectors (not tested here) + *********************************************************************/ + + typedef MultiVecTraits MVT; + typedef Teuchos::ScalarTraits SCT; + typedef typename SCT::magnitudeType MagType; + + const ScalarType one = SCT::one(); + const ScalarType zero = SCT::zero(); + const MagType zero_mag = Teuchos::ScalarTraits::zero(); + + // Don't change these two without checking the initialization of ind below + const int numvecs = 10; + const int numvecs_2 = 5; + + int i,j; + std::vector ind(numvecs_2); + + /* Initialize indices for selected copies/views + The MVT specialization should not assume that + these are ordered or even distinct. + Also retrieve the edges. + + However, to spice things up, grab the first vector, + last vector, and choose the others randomly. + */ + ind[0] = 0; + ind[numvecs_2-1] = numvecs-1; + for (i=1; istream(Warnings) + << "*** ERROR *** MultiVectorTraits::GetNumberVecs()." << endl + << "Returned <= 0." << endl; + return false; + } + + + /*********** GetVecLength() ****************************************** + Verify: + 1) This number should be strictly positive + *********************************************************************/ + if ( MVT::GetVecLength(*A) <= 0 ) { + om->stream(Warnings) + << "*** ERROR *** MultiVectorTraits::GetVecLength()" << endl + << "Returned <= 0." << endl; + return false; + } + + + /*********** Clone() and MvNorm() ************************************ + Verify: + 1) Clone() allows us to specify the number of vectors + 2) Clone() returns a multivector of the same dimension + 3) Vector norms shouldn't be negative + 4) MvNorm result vector should not be resized + *********************************************************************/ + { + Teuchos::RCP B = MVT::Clone(*A,numvecs); + std::vector norms(2*numvecs); + bool ResizeWarning = false; + if ( MVT::GetNumberVecs(*B) != numvecs ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::Clone()." << endl + << "Did not allocate requested number of vectors." << endl; + return false; + } + if ( MVT::GetVecLength(*B) != MVT::GetVecLength(*A) ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::Clone()." << endl + << "Did not allocate requested number of vectors." << endl; + return false; + } + MVT::MvNorm(*B, &norms); + if ( norms.size() != 2*numvecs && ResizeWarning==false ) { + om->stream(Warnings) + << "*** WARNING *** MultiVecTraits::MvNorm()." << endl + << "Method resized the output vector." << endl; + ResizeWarning = true; + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::Clone()." << endl + << "Vector had negative norm." << endl; + return false; + } + } + } + + + /*********** MvRandom() and MvNorm() and MvInit() ******************** + Verify: + 1) Set vectors to zero + 2) Check that norm is zero + 3) Perform MvRandom. + 4) Verify that vectors aren't zero anymore + 5) Perform MvRandom again. + 6) Verify that vector norms are different than before + + Without knowing something about the random distribution, + this is about the best that we can do, to make sure that MvRandom + did at least *something*. + + Also, make sure vector norms aren't negative. + *********************************************************************/ + { + Teuchos::RCP B = MVT::Clone(*A,numvecs); + std::vector norms(numvecs), norms2(numvecs); + + MVT::MvInit(*B); + MVT::MvNorm(*B, &norms); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvInit() " + << "and MultiVecTraits::MvNorm()" << endl + << "Supposedly zero vector has non-zero norm." << endl; + return false; + } + } + MVT::MvRandom(*B); + MVT::MvNorm(*B, &norms); + MVT::MvRandom(*B); + MVT::MvNorm(*B, &norms2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvRandom()." << endl + << "Random vector was empty (very unlikely)." << endl; + return false; + } + else if ( norms[i] < zero_mag || norms2[i] < zero_mag ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvRandom()." << endl + << "Vector had negative norm." << endl; + return false; + } + else if ( norms[i] == norms2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MutliVecTraits::MvRandom()." << endl + << "Vectors not random enough." << endl; + return false; + } + } + } + + + /*********** MvInit() and MvNorm() *********************************** + A vector of ones of dimension n should have norm sqrt(n) + 1) Init vectors to all ones + 2) Verify that norm is sqrt(n) + 3) Verify that norms aren't negative + + Note: I'm not sure that we can expect this to hold in practice. + Maybe something like abs(norm-sqrt(n)) < SCT::eps() ??? + The sum of 1^2==1 should be n, but what about sqrt(n)? + They may be using a different square root than ScalartTraits + On my iBook G4 and on jeter, this test works. + Right now, this has been demoted to a warning. + *********************************************************************/ + { + Teuchos::RCP B = MVT::Clone(*A,numvecs); + std::vector norms(numvecs); + + MVT::MvInit(*B,one); + MVT::MvNorm(*B, &norms); + bool BadNormWarning = false; + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvRandom()." << endl + << "Vector had negative norm." << endl; + return false; + } + else if ( norms[i] != SCT::squareroot(MVT::GetVecLength(*B)) && !BadNormWarning ) { + om->stream(Warnings) + << endl + << "Warning testing MultiVecTraits::MvInit()." << endl + << "Ones vector should have norm sqrt(dim)." << endl + << "norms[i]: " << norms[i] << "\tdim: " << MVT::GetVecLength(*B) << endl << endl; + BadNormWarning = true; + } + } + } + + + /*********** MvInit() and MvNorm() *********************************** + A vector of zeros of dimension n should have norm 0 + 1) Verify that norms aren't negative + 2) Verify that norms are zero + + We must know this works before the next tests. + *********************************************************************/ + { + Teuchos::RCP B = MVT::Clone(*A,numvecs); + std::vector norms(numvecs); + MVT::MvInit(*B, zero_mag); + MVT::MvNorm(*B, &norms); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvInit()." << endl + << "Vector had negative norm." << endl; + return false; + } + else if ( norms[i] != zero_mag ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvInit()." << endl + << "Zero vector should have norm zero." << endl; + return false; + } + } + } + + + /*********** CloneCopy(MV,vector) and MvNorm ******************** + 1) Check quantity/length of vectors + 2) Check vector norms for agreement + 3) Zero out B and make sure that C norms are not affected + *********************************************************************/ + { + Teuchos::RCP B, C; + std::vector norms(numvecs), norms2(numvecs); + + B = MVT::Clone(*A,numvecs); + MVT::MvRandom(*B); + MVT::MvNorm(*B, &norms); + C = MVT::CloneCopy(*B,ind); + MVT::MvNorm(*C, &norms2); + if ( MVT::GetNumberVecs(*C) != numvecs_2 ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl + << "Wrong number of vectors." << endl; + return false; + } + if ( MVT::GetVecLength(*C) != MVT::GetVecLength(*B) ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl + << "Vector lengths don't match." << endl; + return false; + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl + << "Copied vectors do not agree:" + << norms2[i] << " != " << norms[ind[i]] << endl; + return false; + } + } + MVT::MvInit(*B,zero); + MVT::MvNorm(*C, &norms); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy(ind)." << endl + << "Copied vectors were not independent." << endl; + return false; + } + } + } + + + /*********** CloneCopy(MV) and MvNorm ******************************** + 1) Check quantity + 2) Check value of norms + 3) Zero out B and make sure that C is still okay + *********************************************************************/ + { + Teuchos::RCP B, C; + std::vector norms(numvecs), norms2(numvecs); + + B = MVT::Clone(*A,numvecs); + MVT::MvRandom(*B); + MVT::MvNorm(*B, &norms); + C = MVT::CloneCopy(*B); + MVT::MvNorm(*C, &norms2); + if ( MVT::GetNumberVecs(*C) != numvecs ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy()." << endl + << "Wrong number of vectors." << endl; + return false; + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy()." << endl + << "Copied vectors do not agree." << endl; + return false; + } + } + MVT::MvInit(*B,zero); + MVT::MvNorm(*C, &norms); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneCopy()." << endl + << "Copied vectors were not independent." << endl; + return false; + } + } + } + + + /*********** CloneView(MV,vector) and MvNorm ******************** + Check that we have a view of the selected vectors + 1) Check quantity + 2) Check value of norms + 3) Zero out B and make sure that C is zero as well + *********************************************************************/ + { + Teuchos::RCP B, C; + std::vector norms(numvecs), norms2(numvecs); + + B = MVT::Clone(*A,numvecs); + MVT::MvRandom(*B); + MVT::MvNorm(*B, &norms); + C = MVT::CloneView(*B,ind); + MVT::MvNorm(*C, &norms2); + if ( MVT::GetNumberVecs(*C) != numvecs_2 ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneView(ind)." << endl + << "Wrong number of vectors." << endl; + return false; + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::CloneView(ind)." << endl + << "Viewed vectors do not agree." << endl; + return false; + } + } + /* + MVT::MvInit(*B,zero); + MVT::MvNorm(*C, &norms2); + for (i=0; iisVerbosityAndPrint(Warnings) ) { + out << "*** ERROR *** MultiVecTraits::CloneView(ind)." << endl + << "Copied vectors were not dependent." << endl; + } + return false; + } + } + */ + } + + + /*********** const CloneView(MV,vector) and MvNorm() ************ + Check that we have a view of the selected vectors. + 1) Check quantity + 2) Check value of norms for agreement + 3) Zero out B and make sure that C is zerod as well + *********************************************************************/ + { + Teuchos::RCP B; + Teuchos::RCP constB, C; + std::vector normsB(numvecs), normsC(numvecs_2); + std::vector allind(numvecs); + for (i=0; istream(Warnings) + << "*** ERROR *** const MultiVecTraits::CloneView(ind)." << endl + << "Wrong number of vectors." << endl; + return false; + } + for (i=0; istream(Warnings) + << "*** ERROR *** const MultiVecTraits::CloneView(ind)." << endl + << "Viewed vectors do not agree." << endl; + return false; + } + } + /* + MVT::MvInit(const_cast(*C),zero); + MVT::MvNorm(*constB, &normsB); + for (i=0; iisVerbosityAndPrint(Warnings) ) { + out << "*** ERROR *** const MultiVecTraits::CloneView(ind)." << endl + << "Copied vectors were not dependent." << endl; + } + return false; + } + } + */ + } + + + /*********** SetBlock() and MvNorm() ********************************* + SetBlock() will copy the vectors from C into B + 1) Verify that the specified vectors were copied + 2) Verify that the other vectors were not modified + 3) Verify that C was not modified + 4) Change C and then check B to make sure it was not modified + + Use a different index set than has been used so far (distinct entries). + This is because duplicate entries will cause the vector to be + overwritten, making it more difficult to test. + *********************************************************************/ + { + Teuchos::RCP B, C; + std::vector normsB1(numvecs), normsB2(numvecs), + normsC1(numvecs_2), normsC2(numvecs_2); + + B = MVT::Clone(*A,numvecs); + C = MVT::Clone(*A,numvecs_2); + // Just do every other one, interleaving the vectors of C into B + ind.resize(numvecs_2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Operation modified source vectors." << endl; + return false; + } + } + // check that the correct vectors of B were modified + // and the others were not + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Copied vectors do not agree." << endl; + return false; + } + } + else { + // should be an original vector + if ( normsB1[i] != normsB2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Incorrect vectors were modified." << endl; + return false; + } + } + } + MVT::MvInit(*C,zero); + MVT::MvNorm(*B,&normsB1); + // verify that we copied and didn't reference + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Copied vectors were not independent." << endl; + return false; + } + } + } + + + /*********** SetBlock() and MvNorm() ********************************* + SetBlock() will copy the vectors from C into B + 1) Verify that the specified vectors were copied + 2) Verify that the other vectors were not modified + 3) Verify that C was not modified + 4) Change C and then check B to make sure it was not modified + + Use a different index set than has been used so far (distinct entries). + This is because duplicate entries will cause the vector to be + overwritten, making it more difficult to test. + + These tests are the same as the ones above, except that the + number of indices (to be copied into B) is less than the number + of vectors in C, so that not all of C is put into B. + *********************************************************************/ + { + Teuchos::RCP B, C; + // set these: we assume below that setSize*2=BSize + const int BSize = 10, + CSize = 6, + setSize = 5; + std::vector normsB1(BSize), normsB2(BSize), + normsC1(CSize), normsC2(CSize); + + B = MVT::Clone(*A,BSize); + C = MVT::Clone(*A,CSize); + // Just do every other one, interleaving the vectors of C into B + ind.resize(setSize); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Operation modified source vectors." << endl; + return false; + } + } + // check that the correct vectors of B were modified + // and the others were not + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Copied vectors do not agree." << endl; + return false; + } + } + else { + // should be an original vector + if ( normsB1[i] != normsB2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Incorrect vectors were modified." << endl; + return false; + } + } + } + MVT::MvInit(*C,zero); + MVT::MvNorm(*B,&normsB1); + // verify that we copied and didn't reference + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::SetBlock()." << endl + << "Copied vectors were not independent." << endl; + return false; + } + } + } + + + /*********** MvTransMv() ********************************************* + Performs C = alpha * A^H * B, where + alpha is type ScalarType + A,B are type MV with p and q vectors, respectively + C is a SerialDenseMatrix ALREADY sized to p by q + + Verify: + 1) C is not resized by the routine + 3) Check that zero*(A^H B) == zero + 3) Check inner product inequality: + [ |a1|*|b1| ... |ap|*|b1| ] + [a1 ... ap]^H [b1 ... bq] <= [ ... |ai|*|bj| ... ] + [ |ap|*|b1| ... |ap|*|bq| ] + 4) Zero B and check that C is zero + 5) Zero A and check that C is zero + + Note: Should we really require that C is correctly sized already? + Epetra does (and crashes if it isn't.) + *********************************************************************/ + { + const int p = 7; + const int q = 9; + Teuchos::RCP B, C; + std::vector normsB(p), normsC(q); + Teuchos::SerialDenseMatrix SDM(p,q); + + B = MVT::Clone(*A,p); + C = MVT::Clone(*A,q); + + // randomize the multivectors + MVT::MvRandom(*B); + MVT::MvNorm(*B,&normsB); + MVT::MvRandom(*C); + MVT::MvNorm(*C,&normsC); + + // perform SDM = zero() * B^H * C + MVT::MvTransMv( zero, *B, *C, SDM ); + + // check the sizes: not allowed to have shrunk + if ( SDM.numRows() != p || SDM.numCols() != q ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl + << "Routine resized SerialDenseMatrix." << endl; + return false; + } + + // check that zero**A^H*B == zero + if ( SDM.normOne() != zero ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl + << "Scalar argument processed incorrectly." << endl; + return false; + } + + // perform SDM = one * B^H * C + MVT::MvTransMv( one, *B, *C, SDM ); + + // check the norms: a^H b = |a| |b| cos(theta) <= |a| |b| + // with equality only when a and b are colinear + for (i=0; i SCT::magnitude(normsB[i]*normsC[j]) ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl + << "Triangle inequality did not hold: " + << SCT::magnitude(SDM(i,j)) + << " > " + << SCT::magnitude(normsB[i]*normsC[j]) + << endl; + return false; + } + } + } + MVT::MvInit(*C); + MVT::MvRandom(*B); + MVT::MvTransMv( one, *B, *C, SDM ); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl + << "Inner products not zero for C==0." << endl; + return false; + } + } + } + MVT::MvInit(*B); + MVT::MvRandom(*C); + MVT::MvTransMv( one, *B, *C, SDM ); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTransMv()." << endl + << "Inner products not zero for B==0." << endl; + return false; + } + } + } + } + + + /*********** MvDot() ************************************************* + Verify: + 1) Results vector not resized + 2) Inner product inequalities are satisfied + 3) Zero vectors give zero inner products + *********************************************************************/ + { + const int p = 7; + const int q = 9; + Teuchos::RCP B, C; + std::vector iprods(p+q); + std::vector normsB(numvecs), normsC(numvecs); + + B = MVT::Clone(*A,p); + C = MVT::Clone(*A,p); + + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB); + MVT::MvNorm(*C,&normsC); + MVT::MvDot( *B, *C, &iprods ); + if ( iprods.size() != p+q ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvDot." << endl + << "Routine resized results vector." << endl; + return false; + } + for (i=0; i SCT::magnitude(normsB[i]*normsC[i]) ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvDot()." << endl + << "Inner products not valid." << endl; + return false; + } + } + MVT::MvInit(*B); + MVT::MvRandom(*C); + MVT::MvDot( *B, *C, &iprods ); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvDot()." << endl + << "Inner products not zero for B==0." << endl; + return false; + } + } + MVT::MvInit(*C); + MVT::MvRandom(*B); + MVT::MvDot( *B, *C, &iprods ); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvDot()." << endl + << "Inner products not zero for C==0." << endl; + return false; + } + } + } + + + /*********** MvAddMv() *********************************************** + D = alpha*B + beta*C + 1) Use alpha==0,beta==1 and check that D == C + 2) Use alpha==1,beta==0 and check that D == B + 3) Use D==0 and D!=0 and check that result is the same + 4) Check that input arguments are not modified + *********************************************************************/ + { + const int p = 7; + Teuchos::RCP B, C, D; + std::vector normsB1(p), normsB2(p), + normsC1(p), normsC2(p), + normsD1(p), normsD2(p); + ScalarType alpha = SCT::random(), + beta = SCT::random(); + + B = MVT::Clone(*A,p); + C = MVT::Clone(*A,p); + D = MVT::Clone(*A,p); + + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + + // check that 0*B+1*C == C + MVT::MvAddMv(zero,*B,one,*C,*D); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + MVT::MvNorm(*D,&normsD1); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsC1[i] != normsC2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsC1[i] != normsD1[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Assignment did not work." << endl; + return false; + } + } + + // check that 1*B+0*C == B + MVT::MvAddMv(one,*B,zero,*C,*D); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + MVT::MvNorm(*D,&normsD1); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsC1[i] != normsC2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsB1[i] != normsD1[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Assignment did not work." << endl; + return false; + } + } + + // check that alpha*B+beta*C -> D is invariant under initial D + // first, try random D + MVT::MvRandom(*D); + MVT::MvAddMv(alpha,*B,beta,*C,*D); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + MVT::MvNorm(*D,&normsD1); + // check that input args are not modified + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsC1[i] != normsC2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + } + // next, try zero D + MVT::MvInit(*D); + MVT::MvAddMv(alpha,*B,beta,*C,*D); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + MVT::MvNorm(*D,&normsD2); + // check that input args are not modified and that D is the same + // as the above test + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsC1[i] != normsC2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Input arguments were modified." << endl; + return false; + } + else if ( normsD1[i] != normsD2[i] ) { + om->stream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv()." << endl + << "Results varies depending on initial state of dest vectors." << endl; + return false; + } + } + } + + /*********** MvAddMv() *********************************************** + Similar to above, but where B or C are potentially the same + object as D. This case is commonly used, for example, to affect + A <- alpha*A + via + MvAddMv(alpha,A,zero,A,A) + ** OR ** + MvAddMv(zero,A,alpha,A,A) + + The result is that the operation has to be "atomic". That is, + B and C are no longer reliable after D is modified, so that + the assignment to D must be the last thing to occur. + + D = alpha*B + beta*C + + 1) Use alpha==0,beta==1 and check that D == C + 2) Use alpha==1,beta==0 and check that D == B + *********************************************************************/ + { + const int p = 7; + Teuchos::RCP B, C, D; + std::vector normsB(p), + normsD(p); + std::vector lclindex(p); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv() #2" << endl + << "Assignment did not work." << endl; + return false; + } + } + + // check that 1*B+0*C == B + MVT::MvAddMv(one,*B,zero,*C,*D); + MVT::MvNorm(*D,&normsD); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvAddMv() #2" << endl + << "Assignment did not work." << endl; + return false; + } + } + + } + + + /*********** MvTimesMatAddMv() 7 by 5 ******************************** + C = alpha*B*SDM + beta*C + 1) Use alpha==0, SDM!=0, beta==1 and check that C is unchanged + 2) Use alpha==0, SDM!=0, beta==0 and check that C is set to zero + 3) Use alpha==1, SDM==I, beta==0 and check that C is set to B + 4) Use alpha==1, SDM==0, beta==1 and check that C is unchanged + 5) Test with non-square matrices + 6) Always check that input arguments are not modified + *********************************************************************/ + { + const int p = 7, q = 5; + Teuchos::RCP B, C; + Teuchos::SerialDenseMatrix SDM(p,q); + std::vector normsC1(q), normsC2(q), + normsB1(p), normsB2(p); + + B = MVT::Clone(*A,p); + C = MVT::Clone(*A,q); + + // Test 1: alpha==0, SDM!=0, beta==1 and check that C is unchanged + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.random(); + MVT::MvTimesMatAddMv(zero,*B,SDM,one,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 1 failed." << endl; + return false; + } + } + + // Test 2: alpha==0, SDM!=0, beta==0 and check that C is set to zero + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.random(); + MVT::MvTimesMatAddMv(zero,*B,SDM,zero,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 2 failed: " + << normsC2[i] + << " != " + << zero + << endl; + return false; + } + } + + // Test 3: alpha==1, SDM==|I|, beta==0 and check that C is set to B + // |0| + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.scale(zero); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 3 failed: " + << normsB1[i] + << " != " + << normsC2[i] + << endl; + return false; + } + } + + // Test 4: alpha==1, SDM==0, beta==1 and check that C is unchanged + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.scale(zero); + MVT::MvTimesMatAddMv(one,*B,SDM,one,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 4 failed." << endl; + return false; + } + } + } + + /*********** MvTimesMatAddMv() 5 by 7 ******************************** + C = alpha*B*SDM + beta*C + 1) Use alpha==0, SDM!=0, beta==1 and check that C is unchanged + 2) Use alpha==0, SDM!=0, beta==0 and check that C is set to zero + 3) Use alpha==1, SDM==I, beta==0 and check that C is set to B + 4) Use alpha==1, SDM==0, beta==1 and check that C is unchanged + 5) Test with non-square matrices + 6) Always check that input arguments are not modified + *********************************************************************/ + { + const int p = 5, q = 7; + Teuchos::RCP B, C; + Teuchos::SerialDenseMatrix SDM(p,q); + std::vector normsC1(q), normsC2(q), + normsB1(p), normsB2(p); + + B = MVT::Clone(*A,p); + C = MVT::Clone(*A,q); + + // Test 5: alpha==0, SDM!=0, beta==1 and check that C is unchanged + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.random(); + MVT::MvTimesMatAddMv(zero,*B,SDM,one,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 5 failed." << endl; + return false; + } + } + + // Test 6: alpha==0, SDM!=0, beta==0 and check that C is set to zero + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.random(); + MVT::MvTimesMatAddMv(zero,*B,SDM,zero,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 6 failed: " + << normsC2[i] + << " != " + << zero + << endl; + return false; + } + } + + // Test 7: alpha==1, SDM==[I 0], beta==0 and check that C is set to B + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.scale(zero); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 7 failed." << endl; + return false; + } + } + for (i=p; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 7 failed." << endl; + return false; + } + } + + // Test 8: alpha==1, SDM==0, beta==1 and check that C is unchanged + MVT::MvRandom(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + MVT::MvNorm(*C,&normsC1); + SDM.scale(zero); + MVT::MvTimesMatAddMv(one,*B,SDM,one,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Input vectors were modified." << endl; + return false; + } + } + for (i=0; istream(Warnings) + << "*** ERROR *** MultiVecTraits::MvTimesMatAddMv()." << endl + << "Arithmetic test 8 failed." << endl; + return false; + } + } + } + + return true; + + } + + + +/*! \brief This function tests the correctness of an operator implementation + * with respect to an OperatorTraits specialization + * + * \return Status of the test: true is successful, false otherwise. +*/ + template< class ScalarType, class MV, class OP> + bool TestOperatorTraits( + const Teuchos::RCP > &om, + const Teuchos::RCP &A, + const Teuchos::RCP &M) { + + using std::endl; + + /* OPT Contract: + Apply() + MV: OP*zero == zero + Warn if OP is not deterministic (OP*A != OP*A) + Does not modify input arguments + *********************************************************************/ + + typedef MultiVecTraits MVT; + typedef Teuchos::ScalarTraits SCT; + typedef OperatorTraits OPT; + typedef typename SCT::magnitudeType MagType; + + const int numvecs = 10; + + Teuchos::RCP B = MVT::Clone(*A,numvecs), + C = MVT::Clone(*A,numvecs); + + std::vector normsB1(numvecs), normsB2(numvecs), + normsC1(numvecs), normsC2(numvecs); + bool NonDeterministicWarning; + int i; + + + /*********** Apply() ************************************************* + Verify: + 1) OP*B == OP*B; OP is deterministic (just warn on this) + 2) OP*zero == 0 + 3) OP*B doesn't modify B + 4) OP*B is invariant under initial state of destination vectors + *********************************************************************/ + MVT::MvInit(*B); + MVT::MvRandom(*C); + MVT::MvNorm(*B,&normsB1); + OPT::Apply(*M,*B,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + for (i=0; istream(Warnings) + << "*** ERROR *** OperatorTraits::Apply() [1]" << endl + << "Apply() modified the input vectors." << endl; + return false; + } + if (normsC2[i] != SCT::zero()) { + om->stream(Warnings) + << "*** ERROR *** OperatorTraits::Apply() [1]" << endl + << "Operator applied to zero did not return zero." << endl; + return false; + } + } + + // If we send in a random matrix, we should not get a zero return + MVT::MvRandom(*B); + MVT::MvNorm(*B,&normsB1); + OPT::Apply(*M,*B,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + bool ZeroWarning = false; + for (i=0; istream(Warnings) + << "*** ERROR *** OperatorTraits::Apply() [2]" << endl + << "Apply() modified the input vectors." << endl; + return false; + } + if (normsC2[i] == SCT::zero() && ZeroWarning==false ) { + om->stream(Warnings) + << "*** ERROR *** OperatorTraits::Apply() [2]" << endl + << "Operator applied to random vectors returned zero." << endl; + ZeroWarning = true; + } + } + + // Apply operator with C init'd to zero + MVT::MvRandom(*B); + MVT::MvNorm(*B,&normsB1); + MVT::MvInit(*C); + OPT::Apply(*M,*B,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC1); + for (i=0; istream(Warnings) + << "*** ERROR *** OperatorTraits::Apply() [3]" << endl + << "Apply() modified the input vectors." << endl; + return false; + } + } + + // Apply operator with C init'd to random + // Check that result is the same as before; warn if not. + // This could be a result of a bug, or a non-constant + // operator. We do not want to prejudice against a + // stochastic operator. + MVT::MvRandom(*C); + OPT::Apply(*M,*B,*C); + MVT::MvNorm(*B,&normsB2); + MVT::MvNorm(*C,&normsC2); + NonDeterministicWarning = false; + for (i=0; istream(Warnings) + << "*** ERROR *** OperatorTraits::Apply() [4]" << endl + << "Apply() modified the input vectors." << endl; + return false; + } + if (normsC1[i] != normsC2[i] && !NonDeterministicWarning) { + om->stream(Warnings) + << endl + << "*** WARNING *** OperatorTraits::Apply() [4]" << endl + << "Apply() returned two different results." << endl << endl; + NonDeterministicWarning = true; + } + } + + return true; + + } + +} + +#endif diff --git a/fastlib/trilinos/include/AnasaziMatOrthoManager.hpp b/fastlib/trilinos/include/AnasaziMatOrthoManager.hpp new file mode 100644 index 0000000000..d4c3327ce4 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziMatOrthoManager.hpp @@ -0,0 +1,421 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziMatOrthoManager.hpp + \brief Templated virtual class for providing orthogonalization/orthonormalization methods with matrix-based + inner products. +*/ + +#ifndef ANASAZI_MATORTHOMANAGER_HPP +#define ANASAZI_MATORTHOMANAGER_HPP + +/*! \class Anasazi::MatOrthoManager + + \brief Anasazi's templated virtual class for providing routines for orthogonalization and + orthonormalization of multivectors using matrix-based inner products. + + This class extends Anasazi::OrthoManager by providing extra calling arguments to orthogonalization + routines, to reduce the cost of applying the inner product in cases where the user already + has the image of the source multivector under the inner product matrix. + + A concrete implementation of this class is necessary. The user can create + their own implementation if those supplied are not suitable for their needs. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "AnasaziOrthoManager.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" + +namespace Anasazi { + + template + class MatOrthoManager : public OrthoManager { + public: + //! @name Constructor/Destructor + //@{ + //! Default constructor. + MatOrthoManager(Teuchos::RCP Op = Teuchos::null); + + //! Destructor. + virtual ~MatOrthoManager() {}; + //@} + + //! @name Accessor routines + //@{ + + //! Set operator used for inner product. + void setOp( Teuchos::RCP Op ); + + //! Get operator used for inner product. + Teuchos::RCP getOp() const; + + //! Retrieve operator counter. + /*! This counter returns the number of applications of the operator specifying the inner + * product. When the operator is applied to a multivector, the counter is incremented by the + * number of vectors in the multivector. If the operator is not specified, the counter is never + * incremented. + */ + int getOpCounter() const; + + //! Reset the operator counter to zero. + /*! See getOpCounter() for more details. + */ + void resetOpCounter(); + + //@} + + //! @name Matrix-based Orthogonality Methods + //@{ + + /*! \brief Provides a matrix-based inner product. + * + * Provides the inner product + * \f[ + * \langle x, y \rangle = x^H M y + * \f] + * Optionally allows the provision of \f$M y\f$. See OrthoManager::innerProd() for more details. + * + */ + void innerProdMat( const MV& X, const MV& Y, Teuchos::RCP MY, + Teuchos::SerialDenseMatrix& Z ) const; + + /*! \brief Provides the norm induced by the matrix-based inner product. + * + * Provides the norm: + * \f[ + * \|x\|_M = \sqrt{x^T H y} + * \f] + * Optionally allows the provision of \f$M x\f$. See OrthoManager::norm() for more details. + */ + void normMat(const MV& X, Teuchos::RCP MX, + std::vector< typename Teuchos::ScalarTraits::magnitudeType > *normvec ) const; + + /*! \brief Provides matrix-based projection method. + * + * This method optionally allows the provision of \f$M X\f$. See OrthoManager::project() for more details. + */ + virtual void projectMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const = 0; + + /*! \brief Provides matrix-based orthonormalization method. + * + * This method optionally allows the provision of \f$M X\f$. See orthoManager::normalize() for more details. + */ + virtual int normalizeMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::RCP > B = Teuchos::null ) const = 0; + + + /*! \brief Provides matrix-based projection/orthonormalization method. + * + * This method optionally allows the provision of \f$M X\f$. See orthoManager::projectAndNormalize() for more details. + */ + virtual int projectAndNormalizeMat ( + MV &X, Teuchos::RCP MX = Teuchos::null, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::RCP > B = Teuchos::null, + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const = 0; + + /*! \brief This method computes the error in orthonormality of a multivector. + * + * This method optionally allows optionally exploits a caller-provided \c MX. + */ + virtual typename Teuchos::ScalarTraits::magnitudeType + orthonormErrorMat(const MV &X, Teuchos::RCP MX = Teuchos::null) const = 0; + + /*! \brief This method computes the error in orthogonality of two multivectors. + * + * This method optionally allows optionally exploits a caller-provided \c MX. + */ + virtual typename Teuchos::ScalarTraits::magnitudeType + orthogErrorMat(const MV &X1, Teuchos::RCP MX1, const MV &X2) const = 0; + + //@} + + //! @name Methods implementing Anasazi::OrthoManager + //@{ + + /*! \brief Implements the interface OrthoManager::innerProd(). + * + * This method calls + * \code + * innerProdMat(X,Teuchos::null,Y,Z); + * \endcode + */ + void innerProd( const MV& X, const MV& Y, Teuchos::SerialDenseMatrix& Z ) const; + + /*! \brief Implements the interface OrthoManager::norm(). + * + * This method calls + * \code + * normMat(X,Teuchos::null,normvec); + * \endcode + */ + void norm( const MV& X, std::vector< typename Teuchos::ScalarTraits::magnitudeType > *normvec ) const; + + /*! \brief Implements the interface OrthoManager::project(). + * + * This method calls + * \code + * projectMat(X,Teuchos::null,C,Z); + * \endcode + */ + void project ( MV &X, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null)) const; + + /*! \brief Implements the interface OrthoManager::normalize(). + * + * This method calls + * \code + * normalizeMat(X,Teuchos::null,B); + * \endcode + */ + int normalize ( MV &X, Teuchos::RCP > B = Teuchos::null) const; + + /*! \brief Implements the interface OrthoManager::projectAndNormalize(). + * + * This method calls + * \code + * projectAndNormalizeMat(X,Teuchos::null,C,B,Q); + * \endcode + */ + int projectAndNormalize ( MV &X, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::RCP > B = Teuchos::null, + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const; + + /*! \brief Implements the interface OrthoManager::orthonormError(). + * + * This method calls + * \code + * orthonormErrorMat(X,Teuchos::null); + * \endcode + */ + typename Teuchos::ScalarTraits::magnitudeType + orthonormError(const MV &X) const; + + /*! \brief Implements the interface OrthoManager::orthogError(). + * + * This method calls + * \code + * orthogErrorMat(X1,Teuchos::null,X2); + * \endcode + */ + typename Teuchos::ScalarTraits::magnitudeType + orthogError(const MV &X1, const MV &X2) const; + + //@} + + protected: + Teuchos::RCP _Op; + bool _hasOp; + mutable int _OpCounter; + + }; + + template + MatOrthoManager::MatOrthoManager(Teuchos::RCP Op) + : _Op(Op), _hasOp(Op!=Teuchos::null) {} + + template + void MatOrthoManager::setOp( Teuchos::RCP Op ) + { + _Op = Op; + _hasOp = (_Op != Teuchos::null); + } + + template + Teuchos::RCP MatOrthoManager::getOp() const + { + return _Op; + } + + template + int MatOrthoManager::getOpCounter() const + { + return _OpCounter; + } + + template + void MatOrthoManager::resetOpCounter() + { + _OpCounter = 0; + } + + template + void MatOrthoManager::innerProd( + const MV& X, const MV& Y, Teuchos::SerialDenseMatrix& Z ) const + { + typedef Teuchos::ScalarTraits SCT; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + + Teuchos::RCP P,Q; + Teuchos::RCP R; + + if (_hasOp) { + // attempt to minimize the amount of work in applying + if ( MVT::GetNumberVecs(X) < MVT::GetNumberVecs(Y) ) { + R = MVT::Clone(X,MVT::GetNumberVecs(X)); + OPT::Apply(*_Op,X,*R); + _OpCounter += MVT::GetNumberVecs(X); + P = R; + Q = Teuchos::rcp( &Y, false ); + } + else { + P = Teuchos::rcp( &X, false ); + R = MVT::Clone(Y,MVT::GetNumberVecs(Y)); + OPT::Apply(*_Op,Y,*R); + _OpCounter += MVT::GetNumberVecs(Y); + Q = R; + } + } + else { + P = Teuchos::rcp( &X, false ); + Q = Teuchos::rcp( &Y, false ); + } + + MVT::MvTransMv(SCT::one(),*P,*Q,Z); + } + + template + void MatOrthoManager::innerProdMat( + const MV& X, const MV& Y, Teuchos::RCP MY, Teuchos::SerialDenseMatrix& Z ) const + { + typedef Teuchos::ScalarTraits SCT; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + + Teuchos::RCP P,Q; + + if ( MY == Teuchos::null ) { + innerProd(X,Y,Z); + } + else if ( _hasOp ) { + // the user has done the matrix vector for us + MVT::MvTransMv(SCT::one(),X,*MY,Z); + } + else { + // there is no matrix vector + MVT::MvTransMv(SCT::one(),X,Y,Z); + } + } + + template + void MatOrthoManager::norm( + const MV& X, std::vector< typename Teuchos::ScalarTraits::magnitudeType > *normvec ) const + { + this->normMat(X,Teuchos::null,normvec); + } + + template + void MatOrthoManager::normMat( + const MV& X, Teuchos::RCP MX, + std::vector< typename Teuchos::ScalarTraits::magnitudeType > *normvec ) const + { + typedef Teuchos::ScalarTraits SCT; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + + if (!_hasOp) { + MX = Teuchos::rcp(&X,false); + } + else if (MX == Teuchos::null) { + Teuchos::RCP R = MVT::Clone(X,MVT::GetNumberVecs(X)); + OPT::Apply(*_Op,X,*R); + _OpCounter += MVT::GetNumberVecs(X); + MX = R; + } + + Teuchos::SerialDenseMatrix z(1,1); + Teuchos::RCP Xi, MXi; + std::vector ind(1); + for (int i=0; i + void MatOrthoManager::project ( + MV &X, + Teuchos::Array > > C, + Teuchos::Array > Q) const + { + this->projectMat(X,Teuchos::null,C,Q); + } + + template + int MatOrthoManager::normalize ( + MV &X, Teuchos::RCP > B ) const + { + return this->normalizeMat(X,Teuchos::null,B); + } + + template + int MatOrthoManager::projectAndNormalize ( + MV &X, + Teuchos::Array > > C, + Teuchos::RCP > B, + Teuchos::Array > Q ) const + { + return this->projectAndNormalizeMat(X,Teuchos::null,C,B,Q); + } + + template + typename Teuchos::ScalarTraits::magnitudeType + MatOrthoManager::orthonormError(const MV &X) const + { + return this->orthonormErrorMat(X,Teuchos::null); + } + + template + typename Teuchos::ScalarTraits::magnitudeType + MatOrthoManager::orthogError(const MV &X1, const MV &X2) const + { + return this->orthogErrorMat(X1,Teuchos::null,X2); + } + +} // end of Anasazi namespace + + +#endif + +// end of file AnasaziMatOrthoManager.hpp diff --git a/fastlib/trilinos/include/AnasaziMultiVec.hpp b/fastlib/trilinos/include/AnasaziMultiVec.hpp new file mode 100644 index 0000000000..13461c29ca --- /dev/null +++ b/fastlib/trilinos/include/AnasaziMultiVec.hpp @@ -0,0 +1,371 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziMultiVec.hpp + \brief Templated virtual class for creating multi-vectors that can interface with the Anasazi::MultiVecTraits class +*/ + +#ifndef ANASAZI_MULTI_VEC_HPP +#define ANASAZI_MULTI_VEC_HPP + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziMultiVecTraits.hpp" + +namespace Anasazi { + + +/*! \class MultiVec + + \brief Anasazi's templated virtual class for constructing a multi-vector that can interface with the + MultiVecTraits class used by the eigensolvers. + + A concrete implementation of this class is necessary. The user can create + their own implementation if those supplied are not suitable for their needs. + + \author Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ +template +class MultiVec { +public: + + //! @name Constructor/Destructor + //@{ + //! Anasazi::MultiVec constructor. + MultiVec() {}; + + //! Anasazi::MultiVec destructor. + virtual ~MultiVec () {}; + + //@} + //! @name Creation methods + //@{ + + /*! \brief Creates a new empty Anasazi::MultiVec containing \c numvecs columns. + + \return Pointer to the new multivector + */ + + virtual MultiVec * Clone ( const int numvecs ) const = 0; + + /*! \brief Creates a new Anasazi::MultiVec and copies contents of \c *this into + the new vector (deep copy). + + \return Pointer to the new multivector + */ + + virtual MultiVec * CloneCopy () const = 0; + + /*! \brief Creates a new Anasazi::MultiVec and copies the selected contents of \c *this + into the new vector (deep copy). The copied + vectors from \c *this are indicated by the \c index.size() indices in \c index. + + \return Pointer to the new multivector + */ + + virtual MultiVec * CloneCopy ( const std::vector& index ) const = 0; + + /*! \brief Creates a new Anasazi::MultiVec that shares the selected contents of \c *this. + The index of the \c numvecs vectors shallow copied from \c *this are indicated by the + indices given in \c index. + + \return Pointer to the new multivector + */ + + virtual MultiVec * CloneView ( const std::vector& index ) = 0; + //@} + + //! @name Attribute methods + //@{ + //! Obtain the vector length of *this. + + virtual int GetVecLength () const = 0; + + //! Obtain the number of vectors in *this. + + virtual int GetNumberVecs () const = 0; + + //@} + //! @name Update methods + //@{ + /*! \brief Update \c *this with \c alpha * \c A * \c B + \c beta * (\c *this). + */ + + virtual void MvTimesMatAddMv ( ScalarType alpha, const MultiVec& A, + const Teuchos::SerialDenseMatrix& B, ScalarType beta ) = 0; + + /*! \brief Replace \c *this with \c alpha * \c A + \c beta * \c B. + */ + + virtual void MvAddMv ( ScalarType alpha, const MultiVec& A, ScalarType beta, const MultiVec& B ) = 0; + + /*! \brief Compute a dense matrix \c B through the matrix-matrix multiply + \c alpha * \c A^T * (\c *this). + */ + + virtual void MvTransMv ( ScalarType alpha, const MultiVec& A, Teuchos::SerialDenseMatrix& B +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) const = 0; + + /*! \brief Compute a vector \c b where the components are the individual dot-products, i.e.\c b[i] = \c A[i]^H*\c this[i] where \c A[i] is the i-th column of A. + */ + + virtual void MvDot ( const MultiVec& A, std::vector* b +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) const = 0; + + //@} + //! @name Norm method + //@{ + + /*! \brief Compute the 2-norm of each individual vector of \c *this. + Upon return, \c normvec[i] holds the 2-norm of the \c i-th vector of \c *this + */ + + virtual void MvNorm ( std::vector::magnitudeType>* normvec ) const = 0; + + //@} + //! @name Initialization methods + //@{ + /*! \brief Copy the vectors in \c A to a set of vectors in \c *this. The \c + numvecs vectors in \c A are copied to a subset of vectors in \c *this + indicated by the indices given in \c index. + */ + + virtual void SetBlock ( const MultiVec& A, const std::vector& index ) = 0; + + /*! \brief Scale each element of the vectors in \c *this with \c alpha. + */ + + virtual void MvScale ( ScalarType alpha ) = 0; + + /*! \brief Scale each element of the \c i-th vector in \c *this with \c alpha[i]. + */ + + virtual void MvScale ( const std::vector& alpha ) = 0; + + /*! \brief Fill the vectors in \c *this with random numbers. + */ + + virtual void MvRandom () = 0; + + /*! \brief Replace each element of the vectors in \c *this with \c alpha. + */ + + virtual void MvInit ( ScalarType alpha ) = 0; + + //@} + //! @name Print method + //@{ + /*! \brief Print \c *this multivector to the \c os output stream. + */ + virtual void MvPrint ( std::ostream& os ) const = 0; + //@} + +}; + + + //////////////////////////////////////////////////////////////////// + // + // Implementation of the Anasazi::MultiVecTraits for Anasazi::MultiVec. + // + //////////////////////////////////////////////////////////////////// + + /*! + \brief Template specialization of Anasazi::MultiVecTraits class using the Anasazi::MultiVec virtual + base class. + + Any class that inherits from Anasazi::MultiVec will be accepted by the Anasazi templated solvers due to this + interface to the Anasazi::MultiVecTraits class. + */ + + template + class MultiVecTraits > + { + public: + + //! @name Creation methods + //@{ + + /*! \brief Creates a new empty \c Anasazi::MultiVec containing \c numvecs columns. + + \return Reference-counted pointer to the new \c Anasazi::MultiVec. + */ + static Teuchos::RCP > Clone( const MultiVec& mv, const int numvecs ) + { return Teuchos::rcp( const_cast&>(mv).Clone(numvecs) ); } + + /*! \brief Creates a new \c Anasazi::MultiVec and copies contents of \c mv into the new vector (deep copy). + + \return Reference-counted pointer to the new \c Anasazi::MultiVec. + */ + static Teuchos::RCP > CloneCopy( const MultiVec& mv ) + { return Teuchos::rcp( const_cast&>(mv).CloneCopy() ); } + + /*! \brief Creates a new \c Anasazi::MultiVec and copies the selected contents of \c mv into the new vector (deep copy). + + The copied vectors from \c mv are indicated by the \c index.size() indices in \c index. + \return Reference-counted pointer to the new \c Anasazi::MultiVec. + */ + static Teuchos::RCP > CloneCopy( const MultiVec& mv, const std::vector& index ) + { return Teuchos::rcp( const_cast&>(mv).CloneCopy(index) ); } + + /*! \brief Creates a new \c Anasazi::MultiVec that shares the selected contents of \c mv (shallow copy). + + The index of the \c numvecs vectors shallow copied from \c mv are indicated by the indices given in \c index. + \return Reference-counted pointer to the new \c Anasazi::MultiVec. + */ + static Teuchos::RCP > CloneView( MultiVec& mv, const std::vector& index ) + { return Teuchos::rcp( mv.CloneView(index) ); } + + /*! \brief Creates a new const \c Anasazi::MultiVec that shares the selected contents of \c mv (shallow copy). + + The index of the \c numvecs vectors shallow copied from \c mv are indicated by the indices given in \c index. + \return Reference-counted pointer to the new const \c Anasazi::MultiVec. + */ + static Teuchos::RCP > CloneView( const MultiVec& mv, const std::vector& index ) + { return Teuchos::rcp( const_cast&>(mv).CloneView(index) ); } + + //@} + + //! @name Attribute methods + //@{ + + //! Obtain the vector length of \c mv. + static int GetVecLength( const MultiVec& mv ) + { return mv.GetVecLength(); } + + //! Obtain the number of vectors in \c mv + static int GetNumberVecs( const MultiVec& mv ) + { return mv.GetNumberVecs(); } + + //@} + + //! @name Update methods + //@{ + + /*! \brief Update \c mv with \f$ \alpha AB + \beta mv \f$. + */ + static void MvTimesMatAddMv( ScalarType alpha, const MultiVec& A, + const Teuchos::SerialDenseMatrix& B, + ScalarType beta, MultiVec& mv ) + { mv.MvTimesMatAddMv(alpha, A, B, beta); } + + /*! \brief Replace \c mv with \f$\alpha A + \beta B\f$. + */ + static void MvAddMv( ScalarType alpha, const MultiVec& A, ScalarType beta, const MultiVec& B, MultiVec& mv ) + { mv.MvAddMv(alpha, A, beta, B); } + + /*! \brief Compute a dense matrix \c B through the matrix-matrix multiply \f$ \alpha A^Tmv \f$. + */ + static void MvTransMv( ScalarType alpha, const MultiVec& A, const MultiVec& mv, Teuchos::SerialDenseMatrix& B +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) + { mv.MvTransMv(alpha, A, B +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , conj +#endif + ); } + + /*! \brief Compute a vector \c b where the components are the individual dot-products of the \c i-th columns of \c A and \c mv, i.e.\f$b[i] = A[i]^H mv[i]\f$. + */ + static void MvDot( const MultiVec& mv, const MultiVec& A, std::vector* b +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) + { mv.MvDot( A, b +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , conj +#endif + ); } + + /*! \brief Scale each element of the vectors in \c *this with \c alpha. + */ + static void MvScale ( MultiVec& mv, ScalarType alpha ) + { mv.MvScale( alpha ); } + + /*! \brief Scale each element of the \c i-th vector in \c *this with \c alpha[i]. + */ + static void MvScale ( MultiVec& mv, const std::vector& alpha ) + { mv.MvScale( alpha ); } + + //@} + //! @name Norm method + //@{ + + /*! \brief Compute the 2-norm of each individual vector of \c mv. + Upon return, \c normvec[i] holds the value of \f$||mv_i||_2\f$, the \c i-th column of \c mv. + */ + static void MvNorm( const MultiVec& mv, std::vector::magnitudeType>* normvec ) + { mv.MvNorm(normvec); } + + //@} + //! @name Initialization methods + //@{ + /*! \brief Copy the vectors in \c A to a set of vectors in \c mv indicated by the indices given in \c index. + + The \c numvecs vectors in \c A are copied to a subset of vectors in \c mv indicated by the indices given in \c index, + i.e. mv[index[i]] = A[i]. + */ + static void SetBlock( const MultiVec& A, const std::vector& index, MultiVec& mv ) + { mv.SetBlock(A, index); } + + /*! \brief Replace the vectors in \c mv with random vectors. + */ + static void MvRandom( MultiVec& mv ) + { mv.MvRandom(); } + + /*! \brief Replace each element of the vectors in \c mv with \c alpha. + */ + static void MvInit( MultiVec& mv, ScalarType alpha = Teuchos::ScalarTraits::zero() ) + { mv.MvInit(alpha); } + + //@} + + //! @name Print method + //@{ + + /*! \brief Print the \c mv multi-vector to the \c os output stream. + */ + static void MvPrint( const MultiVec& mv, std::ostream& os ) + { mv.MvPrint(os); } + + //@} + }; + + +} // namespace Anasazi + +#endif + +// end of file AnasaziMultiVec.hpp diff --git a/fastlib/trilinos/include/AnasaziMultiVecTraits.hpp b/fastlib/trilinos/include/AnasaziMultiVecTraits.hpp new file mode 100644 index 0000000000..b5fff6ec58 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziMultiVecTraits.hpp @@ -0,0 +1,216 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// +#ifndef ANASAZI_MULTI_VEC_TRAITS_HPP +#define ANASAZI_MULTI_VEC_TRAITS_HPP + +/*! \file AnasaziMultiVecTraits.hpp + \brief Virtual base class which defines basic traits for the multivector type +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" + +namespace Anasazi { + + /*! \brief This is the default struct used by MultiVecTraits class to produce a + compile time error when the specialization does not exist for multivector type MV. + */ + template< class ScalarType, class MV > + struct UndefinedMultiVecTraits + { + //! This function should not compile if there is an attempt to instantiate! + /*! \note Any attempt to compile this function results in a compile time error. This means + that the template specialization of Anasazi::MultiVecTraits class for type MV does + not exist, or is not complete. + */ + static inline ScalarType notDefined() { return MV::this_type_is_missing_a_specialization(); }; + }; + + + /*! \brief Virtual base class which defines basic traits for the multi-vector type. + + An adapter for this traits class must exist for the MV type. + If not, this class will produce a compile-time error. + + \ingroup anasazi_opvec_interfaces + */ + template + class MultiVecTraits + { + public: + + //! @name Creation methods + //@{ + + /*! \brief Creates a new empty \c MV containing \c numvecs columns. + + \return Reference-counted pointer to the new multivector of type \c MV. + */ + static Teuchos::RCP Clone( const MV& mv, const int numvecs ) + { UndefinedMultiVecTraits::notDefined(); return Teuchos::null; } + + /*! \brief Creates a new \c MV and copies contents of \c mv into the new vector (deep copy). + + \return Reference-counted pointer to the new multivector of type \c MV. + */ + static Teuchos::RCP CloneCopy( const MV& mv ) + { UndefinedMultiVecTraits::notDefined(); return Teuchos::null; } + + /*! \brief Creates a new \c MV and copies the selected contents of \c mv into the new vector (deep copy). + + The copied vectors from \c mv are indicated by the \c index.size() indices in \c index. + \return Reference-counted pointer to the new multivector of type \c MV. + */ + static Teuchos::RCP CloneCopy( const MV& mv, const std::vector& index ) + { UndefinedMultiVecTraits::notDefined(); return Teuchos::null; } + + /*! \brief Creates a new \c MV that shares the selected contents of \c mv (shallow copy). + + The index of the \c numvecs vectors shallow copied from \c mv are indicated by the indices given in \c index. + \return Reference-counted pointer to the new multivector of type \c MV. + */ + static Teuchos::RCP CloneView( MV& mv, const std::vector& index ) + { UndefinedMultiVecTraits::notDefined(); return Teuchos::null; } + + /*! \brief Creates a new const \c MV that shares the selected contents of \c mv (shallow copy). + + The index of the \c numvecs vectors shallow copied from \c mv are indicated by the indices given in \c index. + \return Reference-counted pointer to the new const multivector of type \c MV. + */ + static Teuchos::RCP CloneView( const MV& mv, const std::vector& index ) + { UndefinedMultiVecTraits::notDefined(); return Teuchos::null; } + + //@} + + //! @name Attribute methods + //@{ + + //! Obtain the vector length of \c mv. + static int GetVecLength( const MV& mv ) + { UndefinedMultiVecTraits::notDefined(); return 0; } + + //! Obtain the number of vectors in \c mv + static int GetNumberVecs( const MV& mv ) + { UndefinedMultiVecTraits::notDefined(); return 0; } + + //@} + + //! @name Update methods + //@{ + + /*! \brief Update \c mv with \f$ \alpha AB + \beta mv \f$. + */ + static void MvTimesMatAddMv( const ScalarType alpha, const MV& A, + const Teuchos::SerialDenseMatrix& B, + const ScalarType beta, MV& mv ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Replace \c mv with \f$\alpha A + \beta B\f$. + */ + static void MvAddMv( const ScalarType alpha, const MV& A, const ScalarType beta, const MV& B, MV& mv ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Compute a dense matrix \c B through the matrix-matrix multiply \f$ \alpha A^Hmv \f$. + */ + static void MvTransMv( const ScalarType alpha, const MV& A, const MV& mv, Teuchos::SerialDenseMatrix& B +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Compute a vector \c b where the components are the individual dot-products of the \c i-th columns of \c A and \c mv, i.e.\f$b[i] = A[i]^Hmv[i]\f$. + */ + static void MvDot ( const MV& mv, const MV& A, std::vector* b +#ifdef HAVE_ANASAZI_EXPERIMENTAL + , ConjType conj = Anasazi::CONJ +#endif + ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Scale each element of the vectors in \c mv with \c alpha. + */ + static void MvScale ( MV& mv, const ScalarType alpha ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Scale each element of the \c i-th vector in \c mv with \c alpha[i]. + */ + static void MvScale ( MV& mv, const std::vector& alpha ) + { UndefinedMultiVecTraits::notDefined(); } + + //@} + //! @name Norm method + //@{ + + /*! \brief Compute the 2-norm of each individual vector of \c mv. + Upon return, \c normvec[i] holds the value of \f$||mv_i||_2\f$, the \c i-th column of \c mv. + */ + static void MvNorm( const MV& mv, std::vector::magnitudeType>* normvec ) + { UndefinedMultiVecTraits::notDefined(); } + + //@} + + //! @name Initialization methods + //@{ + /*! \brief Copy the vectors in \c A to a set of vectors in \c mv indicated by the indices given in \c index. + + The \c numvecs vectors in \c A are copied to a subset of vectors in \c mv indicated by the indices given in \c index, + i.e. mv[index[i]] = A[i]. + */ + static void SetBlock( const MV& A, const std::vector& index, MV& mv ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Replace the vectors in \c mv with random vectors. + */ + static void MvRandom( MV& mv ) + { UndefinedMultiVecTraits::notDefined(); } + + /*! \brief Replace each element of the vectors in \c mv with \c alpha. + */ + static void MvInit( MV& mv, const ScalarType alpha = Teuchos::ScalarTraits::zero() ) + { UndefinedMultiVecTraits::notDefined(); } + + //@} + + //! @name Print method + //@{ + + /*! \brief Print the \c mv multi-vector to the \c os output stream. + */ + static void MvPrint( const MV& mv, std::ostream& os ) + { UndefinedMultiVecTraits::notDefined(); } + + //@} + }; + +} // namespace Anasazi + +#endif // ANASAZI_MULTI_VEC_TRAITS_HPP diff --git a/fastlib/trilinos/include/AnasaziOperator.hpp b/fastlib/trilinos/include/AnasaziOperator.hpp new file mode 100644 index 0000000000..b03334739f --- /dev/null +++ b/fastlib/trilinos/include/AnasaziOperator.hpp @@ -0,0 +1,115 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziOperator.hpp + \brief Templated virtual class for creating operators that can interface with the Anasazi::OperatorTraits class +*/ + +#ifndef ANASAZI_OPERATOR_HPP +#define ANASAZI_OPERATOR_HPP + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "AnasaziMultiVec.hpp" +#include "Teuchos_ScalarTraits.hpp" + + +namespace Anasazi { + +/*! + \brief Anasazi's templated virtual class for constructing an operator that can interface with the + OperatorTraits class used by the eigensolvers. + + A concrete implementation of this class is necessary. The user can create their own implementation + if those supplied are not suitable for their needs. + + \author Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + template + class Operator { + public: + //! @name Constructor/Destructor + //@{ + //! Default constructor. + Operator() {}; + + //! Destructor. + virtual ~Operator() {}; + //@} + + //! @name Operator application method + //@{ + + /*! \brief This method takes the Anasazi::MultiVec \c x and + applies the operator to it resulting in the Anasazi::MultiVec \c y. + */ + virtual void Apply ( const MultiVec& x, MultiVec& y ) const = 0; + + //@} + }; + + //////////////////////////////////////////////////////////////////// + // + // Implementation of the Anasazi::OperatorTraits for Anasazi::Operator + // and Anasazi::MultiVec. + // + //////////////////////////////////////////////////////////////////// + + /*! + \brief Template specialization of Anasazi::OperatorTraits class using Anasazi::Operator and Anasazi::MultiVec virtual + base classes. + + Any class that inherits from Anasazi::Operator will be accepted by the Anasazi templated solvers due to this + interface to the Anasazi::OperatorTraits class. + */ + + template + class OperatorTraits < ScalarType, MultiVec, Operator > + { + public: + + //! @name Operator application method + //@{ + + /*! \brief This method takes the Anasazi::MultiVec \c x and + applies the Anasazi::Operator \c Op to it resulting in the Anasazi::MultiVec \c y. + */ + static void Apply ( const Operator& Op, + const MultiVec& x, + MultiVec& y ) + { Op.Apply( x, y ); } + + //@} + + }; + +} // end of Anasazi namespace + +#endif + +// end of file AnasaziOperator.hpp diff --git a/fastlib/trilinos/include/AnasaziOperatorTraits.hpp b/fastlib/trilinos/include/AnasaziOperatorTraits.hpp new file mode 100644 index 0000000000..4018eff20b --- /dev/null +++ b/fastlib/trilinos/include/AnasaziOperatorTraits.hpp @@ -0,0 +1,92 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_OPERATOR_TRAITS_HPP +#define ANASAZI_OPERATOR_TRAITS_HPP + +/*! \file AnasaziOperatorTraits.hpp + \brief Virtual base class which defines basic traits for the operator type +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + + +namespace Anasazi { + + + //! \brief Exceptions thrown to signal error in operator application. + class OperatorError : public AnasaziError + {public: OperatorError(const std::string& what_arg) : AnasaziError(what_arg) {}}; + + + /*! \brief This is the default struct used by OperatorTraits class to produce a + compile time error when the specialization does not exist for operator type OP. + */ + template< class ScalarType, class MV, class OP > + struct UndefinedOperatorTraits + { + //! This function should not compile if there is an attempt to instantiate! + /*! \note Any attempt to compile this function results in a compile time error. This means + that the template specialization of Anasazi::OperatorTraits class does not exist for type + OP, or is not complete. + */ + static inline void notDefined() { return OP::this_type_is_missing_a_specialization(); }; + }; + + + /*! \brief Virtual base class which defines basic traits for the operator type. + + An adapter for this traits class must exist for the MV and OP types. + If not, this class will produce a compile-time error. + + \ingroup anasazi_opvec_interfaces + */ + template + class OperatorTraits + { + public: + + //! @name Operator application method. + //@{ + + //! Application method which performs operation y = Op*x. An OperatorError exception is thrown if there is an error. + static void Apply ( const OP& Op, + const MV& x, + MV& y ) + { UndefinedOperatorTraits::notDefined(); }; + + //@} + + }; + +} // end Anasazi namespace + +#endif // ANASAZI_OPERATOR_TRAITS_HPP + +// end of file AnasaziOperatorTraits.hpp diff --git a/fastlib/trilinos/include/AnasaziOrthoManager.hpp b/fastlib/trilinos/include/AnasaziOrthoManager.hpp new file mode 100644 index 0000000000..4e527e5c16 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziOrthoManager.hpp @@ -0,0 +1,268 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +/*! \file AnasaziOrthoManager.hpp + \brief Templated virtual class for providing orthogonalization/orthonormalization methods. +*/ + +#ifndef ANASAZI_ORTHOMANAGER_HPP +#define ANASAZI_ORTHOMANAGER_HPP + +/*! \class Anasazi::OrthoManager + + \brief Anasazi's templated virtual class for providing routines for orthogonalization and + orthonormalization of multivectors. + + This class defines concepts of orthogonality through the definition of an + inner product. It also provides computational routines for orthogonalization. + + A concrete implementation of this class is necessary. The user can create + their own implementation if those supplied are not suitable for their needs. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" +#include "Teuchos_Array.hpp" + + + + +namespace Anasazi { + + + //! @name OrthoManager Exceptions + //@{ + + /** \brief Exception thrown to signal error in an orthogonalization manager method. + */ + class OrthoError : public AnasaziError + {public: OrthoError(const std::string& what_arg) : AnasaziError(what_arg) {}}; + + //@} + + template + class OrthoManager { + public: + //! @name Constructor/Destructor + //@{ + //! Default constructor. + OrthoManager() {}; + + //! Destructor. + virtual ~OrthoManager() {}; + //@} + + //! @name Orthogonalization methods + //@{ + + /*! \brief Provides the inner product defining the orthogonality concepts. + + All concepts of orthogonality discussed in this class are defined with respect to this inner product. + + \note This is potentially different from MultiVecTraits::MvTransMv(). For example, it is customary in many + eigensolvers to exploit a mass matrix \c M for the inner product: \f$x^HMx\f$. + + @param Z [out] Z(i,j) contains the inner product of X[i] and Y[i]: + \f[ + Z(i,j) = \langle X[i], Y[i] \rangle + \f] + + */ + virtual void innerProd( const MV &X, const MV &Y, Teuchos::SerialDenseMatrix& Z ) const = 0; + + + /*! \brief Provides the norm induced by innerProd(). + * + * This computes the norm for each column of a multivector. This is the norm induced by innerProd(): + * \f[ \|x\| = \sqrt{\langle x, x \rangle} \f] + * + * @param normvec [out] Vector of norms, whose \c i-th entry corresponds to the \c i-th column of \c X + */ + virtual void norm( const MV& X, std::vector< typename Teuchos::ScalarTraits::magnitudeType > *normvec ) const = 0; + + /*! \brief Given a list of mutually orthogonal and internally orthonormal bases \c Q, this method + * projects a multivector \c X onto the space orthogonal to the individual Q[i], + * optionally returning the coefficients of \c X for the individual Q[i]. All of this is done with respect + * to the inner product innerProd(). + * + * After calling this routine, \c X will be orthogonal to each of the Q[i]. + * + @param X [in/out] The multivector to be modified.
    + On output, the columns of \c X will be orthogonal to each Q[i], satisfying + \f[ + X_{out} = X_{in} - \sum_i Q[i] \langle Q[i], X_{in} \rangle + \f] + + @param C [out] The coefficients of \c X in the bases Q[i]. If C[i] is a non-null pointer + and C[i] matches the dimensions of \c X and Q[i], then the coefficients computed during the orthogonalization + routine will be stored in the matrix C[i], similar to calling + \code + innerProd( Q[i], X, C[i] ); + \endcode + If C[i] points to a Teuchos::SerialDenseMatrix with size + inconsistent with \c X and \c Q[i], then a std::invalid_argument + exception will be thrown. Otherwise, if C.size() < i or + C[i] is a null pointer, the caller will not have access to the + computed coefficients. + + @param Q [in] A list of multivector bases specifying the subspaces to be orthogonalized against, satisfying + \f[ + \langle Q[i], Q[j] \rangle = I \quad\textrm{if}\quad i=j + \f] + and + \f[ + \langle Q[i], Q[j] \rangle = 0 \quad\textrm{if}\quad i \neq j\ . + \f] + */ + virtual void project ( + MV &X, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const = 0; + + /*! \brief This method takes a multivector \c X and attempts to compute a basis for \f$colspan(X)\f$. This basis is orthonormal with respect to innerProd(). + * + * This routine returns an integer \c rank stating the rank of the computed basis. If \c X does not have full rank and the normalize() routine does + * not attempt to augment the subspace, then \c rank may be smaller than the number of columns in \c X. In this case, only the first \c rank columns of + * output \c X and first \c rank rows of \c B will be valid. + * + @param X [in/out] The multivector to be modified.
    + On output, the first \c rank columns of \c X satisfy + \f[ + \langle X[i], X[j] \rangle = \delta_{ij}\ . + \f] + Also, + \f[ + X_{in}(1:m,1:n) = X_{out}(1:m,1:rank) B(1:rank,1:n) + \f] + where \c m is the number of rows in \c X and \c n is the number of columns in \c X. + + @param B [out] The coefficients of the original \c X with respect to the computed basis. If \c B is a non-null pointer and \c B matches the dimensions of \c B, then the + coefficients computed during the orthogonalization routine will be stored in \c B, similar to calling + \code + innerProd( Xout, Xin, B ); + \endcode + If \c B points to a Teuchos::SerialDenseMatrix with size inconsistent with \c X, then a std::invalid_argument exception will be thrown. Otherwise, if \c B is null, the caller will not have + access to the computed coefficients. This matrix is not necessarily triangular (as in a QR factorization); see the documentation of specific orthogonalization managers. + + @return Rank of the basis computed by this method, less than or equal to the number of columns in \c X. This specifies how many columns in the returned \c X and rows in the returned \c B are valid. + */ + virtual int normalize ( + MV &X, + Teuchos::RCP > B = Teuchos::null) const = 0; + + + /*! \brief Given a set of bases Q[i] and a multivector \c X, this method computes an orthonormal basis for \f$colspan(X) - \sum_i colspan(Q[i])\f$. + * + * This routine returns an integer \c rank stating the rank of the computed basis. If the subspace \f$colspan(X) - \sum_i colspan(Q[i])\f$ does not + * have dimension as large as the number of columns of \c X and the orthogonalization manager does not attempt to augment the subspace, then \c rank + * may be smaller than the number of columns of \c X. In this case, only the first \c rank columns of output \c X and first \c rank rows of \c B will + * be valid. + * + * \note This routine guarantees both the orthogonality of the returned basis against the Q[i] as well as the orthonormality of the returned basis. Therefore, + * this method is not necessarily equivalent to calling project() followed by a call to normalize(); see the documentation for specific orthogonalization managers. + * + @param X [in/out] + On output, the first \c rank columns of \c X satisfy + \f[ + \langle X[i], X[j] \rangle = \delta_{ij} \quad \textrm{and} \quad \langle X, Q[i] \rangle = 0\ . + \f] + Also, + \f[ + X_{in}(1:m,1:n) = X_{out}(1:m,1:rank) B(1:rank,1:n) + \sum_i Q[i] C[i] + \f] + where \c m is the number of rows in \c X and \c n is the number of columns in \c X. + + @param C [out] The coefficients of \c X in the Q[i]. If C[i] is a non-null pointer + and C[i] matches the dimensions of \c X and Q[i], then the coefficients computed during the orthogonalization + routine will be stored in the matrix C[i], similar to calling + \code + innerProd( Q[i], X, C[i] ); + \endcode + If C[i] points to a Teuchos::SerialDenseMatrix with size + inconsistent with \c X and \c Q[i], then a std::invalid_argument + exception will be thrown. Otherwise, if C.size() < i or + C[i] is a null pointer, the caller will not have access to the + computed coefficients. + + @param B [out] The coefficients of the original \c X with respect to the computed basis. If \c B is a non-null pointer and \c B matches the dimensions of \c B, then the + coefficients computed during the orthogonalization routine will be stored in \c B, similar to calling + \code + innerProd( Xout, Xin, B ); + \endcode + If \c B points to a Teuchos::SerialDenseMatrix with size inconsistent with \c X, then a std::invalid_argument exception will be thrown. Otherwise, if \c B is null, the caller will not have + access to the computed coefficients. This matrix is not necessarily triangular (as in a QR factorization); see the documentation of specific orthogonalization managers. + + @param Q [in] A list of multivector bases specifying the subspaces to be orthogonalized against, satisfying + \f[ + \langle Q[i], Q[j] \rangle = I \quad\textrm{if}\quad i=j + \f] + and + \f[ + \langle Q[i], Q[j] \rangle = 0 \quad\textrm{if}\quad i \neq j\ . + \f] + + @return Rank of the basis computed by this method, less than or equal to the number of columns in \c X. This specifies how many columns in the returned \c X and rows in the returned \c B are valid. + */ + virtual int projectAndNormalize ( + MV &X, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::RCP > B = Teuchos::null, + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const = 0; + + //@} + + //! @name Error methods + //@{ + + /*! \brief This method computes the error in orthonormality of a multivector. + * + * This method return some measure of \f$\| \langle X, X \rangle - I \| \f$. See the documentation of specific orthogonalization managers. + */ + virtual typename Teuchos::ScalarTraits< ScalarType >::magnitudeType orthonormError(const MV &X) const = 0; + + /*! \brief This method computes the error in orthogonality of two multivectors. + * + * This method return some measure of \f$\| \langle X1, X2 \rangle - 0 \| \f$. See the documentation of specific orthogonalization managers. + */ + virtual typename Teuchos::ScalarTraits::magnitudeType orthogError(const MV &X1, const MV &X2) const = 0; + + //@} + + }; + +} // end of Anasazi namespace + + +#endif + +// end of file AnasaziOrthoManager.hpp diff --git a/fastlib/trilinos/include/AnasaziOutputManager.hpp b/fastlib/trilinos/include/AnasaziOutputManager.hpp new file mode 100644 index 0000000000..b004b0009b --- /dev/null +++ b/fastlib/trilinos/include/AnasaziOutputManager.hpp @@ -0,0 +1,114 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_OUTPUT_MANAGER_HPP +#define ANASAZI_OUTPUT_MANAGER_HPP + +/*! \file AnasaziOutputManager.hpp + \brief Abstract class definition for Anasazi Output Managers. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +/*! \class Anasazi::OutputManager + + \brief Output managers remove the need for the eigensolver to know any information + about the required output. Calling isVerbosity( MsgType type ) informs the solver if + it is supposed to output the information corresponding to the message type. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +namespace Anasazi { + +template +class OutputManager { + + public: + + //!@name Constructors/Destructor + //@{ + + //! Default constructor + OutputManager( int vb = Anasazi::Errors ) : vb_(vb) {}; + + //! Destructor. + virtual ~OutputManager() {}; + //@} + + //! @name Set/Get methods + //@{ + + //! Set the message output types for this manager. + virtual void setVerbosity( int vb ) { vb_ = vb; } + + //! Get the message output types for this manager. + virtual int getVerbosity( ) const { return vb_; } + + //@} + + //! @name Output methods + //@{ + + //! Find out whether we need to print out information for this message type. + /*! This method is used by the solver to determine whether computations are + necessary for this message type. + */ + virtual bool isVerbosity( MsgType type ) const = 0; + + //! Send output to the output manager. + virtual void print( MsgType type, const std::string output ) = 0; + + //! Create a stream for outputting to. + virtual std::ostream &stream( MsgType type ) = 0; + + //@} + + private: + + //! @name Undefined methods + //@{ + + //! Copy constructor. + OutputManager( const OutputManager& OM ); + + //! Assignment operator. + OutputManager& operator=( const OutputManager& OM ); + + //@} + + protected: + int vb_; +}; + +} // end Anasazi namespace + +#endif + +// end of file AnasaziOutputManager.hpp diff --git a/fastlib/trilinos/include/AnasaziSVQBOrthoManager.hpp b/fastlib/trilinos/include/AnasaziSVQBOrthoManager.hpp new file mode 100644 index 0000000000..b43bb66d0b --- /dev/null +++ b/fastlib/trilinos/include/AnasaziSVQBOrthoManager.hpp @@ -0,0 +1,818 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +/*! \file AnasaziSVQBOrthoManager.hpp + \brief Orthogonalization manager based on the SVQB technique described in + "A Block Orthogonalization Procedure With Constant Synchronization Requirements", A. Stathapoulos and K. Wu +*/ + +#ifndef ANASAZI_SVQB_ORTHOMANAGER_HPP +#define ANASAZI_SVQB_ORTHOMANAGER_HPP + +/*! \class Anasazi::SVQBOrthoManager + \brief An implementation of the Anasazi::MatOrthoManager that performs orthogonalization + using the SVQB iterative orthogonalization technique described by Stathapoulos and Wu. This orthogonalization routine, + while not returning the upper triangular factors of the popular Gram-Schmidt method, has a communication + cost (measured in number of communication calls) that is independent of the number of columns in the basis. + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "AnasaziMatOrthoManager.hpp" +#include "Teuchos_LAPACK.hpp" + +namespace Anasazi { + + template + class SVQBOrthoManager : public MatOrthoManager { + + private: + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits SCT; + typedef Teuchos::ScalarTraits SCTM; + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + std::string dbgstr; + + + public: + + //! @name Constructor/Destructor + //@{ + //! Constructor specifying re-orthogonalization tolerance. + SVQBOrthoManager( Teuchos::RCP Op = Teuchos::null, bool debug = false ); + + + //! Destructor + ~SVQBOrthoManager() {}; + //@} + + + //! @name Methods implementing Anasazi::MatOrthoManager + //@{ + + + /*! \brief Given a list of mutually orthogonal and internally orthonormal bases \c Q, this method + * projects a multivector \c X onto the space orthogonal to the individual Q[i], + * optionally returning the coefficients of \c X for the individual Q[i]. All of this is done with respect + * to the inner product innerProd(). + * + * After calling this routine, \c X will be orthogonal to each of the Q[i]. + * + @param X [in/out] The multivector to be modified.
    + On output, the columns of \c X will be orthogonal to each Q[i], satisfying + \f[ + X_{out} = X_{in} - \sum_i Q[i] \langle Q[i], X_{in} \rangle + \f] + + @param MX [in/out] The image of \c X under the inner product operator \c Op. + If \f$ MX != 0\f$: On input, this is expected to be consistent with \c Op \cdot X. On output, this is updated consistent with updates to \c X. + If \f$ MX == 0\f$ or \f$ Op == 0\f$: \c MX is not referenced. + + @param C [out] The coefficients of \c X in the bases Q[i]. If C[i] is a non-null pointer + and C[i] matches the dimensions of \c X and Q[i], then the coefficients computed during the orthogonalization + routine will be stored in the matrix C[i], similar to calling + \code + innerProd( Q[i], X, C[i] ); + \endcode + If C[i] points to a Teuchos::SerialDenseMatrix with size + inconsistent with \c X and \c Q[i], then a std::invalid_argument + exception will be thrown. Otherwise, if C.size() < i or + C[i] is a null pointer, the caller will not have access to the + computed coefficients. + + @param Q [in] A list of multivector bases specifying the subspaces to be orthogonalized against, satisfying + \f[ + \langle Q[i], Q[j] \rangle = I \quad\textrm{if}\quad i=j + \f] + and + \f[ + \langle Q[i], Q[j] \rangle = 0 \quad\textrm{if}\quad i \neq j\ . + \f] + */ + void projectMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const; + + + /*! \brief This method takes a multivector \c X and attempts to compute an orthonormal basis for \f$colspan(X)\f$, with respect to innerProd(). + * + * This method does not compute an upper triangular coefficient matrix \c B. + * + * This routine returns an integer \c rank stating the rank of the computed basis. If \c X does not have full rank and the normalize() routine does + * not attempt to augment the subspace, then \c rank may be smaller than the number of columns in \c X. In this case, only the first \c rank columns of + * output \c X and first \c rank rows of \c B will be valid. + * + * The method attempts to find a basis with dimension equal to the number of columns in \c X. It does this by augmenting linearly dependent + * vectors in \c X with random directions. A finite number of these attempts will be made; therefore, it is possible that the dimension of the + * computed basis is less than the number of vectors in \c X. + * + @param X [in/out] The multivector to be modified.
    + On output, the first \c rank columns of \c X satisfy + \f[ + \langle X[i], X[j] \rangle = \delta_{ij}\ . + \f] + Also, + \f[ + X_{in}(1:m,1:n) = X_{out}(1:m,1:rank) B(1:rank,1:n) + \f] + where \c m is the number of rows in \c X and \c n is the number of columns in \c X. + + @param MX [in/out] The image of \c X under the inner product operator \c Op. + If \f$ MX != 0\f$: On input, this is expected to be consistent with \c Op \cdot X. On output, this is updated consistent with updates to \c X. + If \f$ MX == 0\f$ or \f$ Op == 0\f$: \c MX is not referenced. + + @param B [out] The coefficients of the original \c X with respect to the computed basis. If \c B is a non-null pointer and \c B matches the dimensions of \c B, then the + coefficients computed during the orthogonalization routine will be stored in \c B, similar to calling + \code + innerProd( Xout, Xin, B ); + \endcode + If \c B points to a Teuchos::SerialDenseMatrix with size inconsistent with \c X, then a std::invalid_argument exception will be thrown. Otherwise, if \c B is null, the caller will not have + access to the computed coefficients. This matrix is not necessarily triangular (as in a QR factorization); see the documentation of specific orthogonalization managers.
    + In general, \c B has no non-zero structure. + + @return Rank of the basis computed by this method, less than or equal to the number of columns in \c X. This specifies how many columns in the returned \c X and rows in the returned \c B are valid. + */ + int normalizeMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::RCP > B = Teuchos::tuple(Teuchos::null) ) const; + + + /*! \brief Given a set of bases Q[i] and a multivector \c X, this method computes an orthonormal basis for \f$colspan(X) - \sum_i colspan(Q[i])\f$. + * + * This routine returns an integer \c rank stating the rank of the computed basis. If the subspace \f$colspan(X) - \sum_i colspan(Q[i])\f$ does not + * have dimension as large as the number of columns of \c X and the orthogonalization manager doe not attempt to augment the subspace, then \c rank + * may be smaller than the number of columns of \c X. In this case, only the first \c rank columns of output \c X and first \c rank rows of \c B will + * be valid. + * + * The method attempts to find a basis with dimension the same as the number of columns in \c X. It does this by augmenting linearly dependent + * vectors with random directions. A finite number of these attempts will be made; therefore, it is possible that the dimension of the + * computed basis is less than the number of vectors in \c X. + * + @param X [in/out] The multivector to be modified.
    + On output, the first \c rank columns of \c X satisfy + \f[ + \langle X[i], X[j] \rangle = \delta_{ij} \quad \textrm{and} \quad \langle X, Q[i] \rangle = 0\ . + \f] + Also, + \f[ + X_{in}(1:m,1:n) = X_{out}(1:m,1:rank) B(1:rank,1:n) + \sum_i Q[i] C[i] + \f] + where \c m is the number of rows in \c X and \c n is the number of columns in \c X. + + @param MX [in/out] The image of \c X under the inner product operator \c Op. + If \f$ MX != 0\f$: On input, this is expected to be consistent with \c Op \cdot X. On output, this is updated consistent with updates to \c X. + If \f$ MX == 0\f$ or \f$ Op == 0\f$: \c MX is not referenced. + + @param C [out] The coefficients of \c X in the Q[i]. If C[i] is a non-null pointer + and C[i] matches the dimensions of \c X and Q[i], then the coefficients computed during the orthogonalization + routine will be stored in the matrix C[i], similar to calling + \code + innerProd( Q[i], X, C[i] ); + \endcode + If C[i] points to a Teuchos::SerialDenseMatrix with size + inconsistent with \c X and \c Q[i], then a std::invalid_argument + exception will be thrown. Otherwise, if C.size() < i or + C[i] is a null pointer, the caller will not have access to the + computed coefficients. + + @param B [out] The coefficients of the original \c X with respect to the computed basis. If \c B is a non-null pointer and \c B matches the dimensions of \c B, then the + coefficients computed during the orthogonalization routine will be stored in \c B, similar to calling + \code + innerProd( Xout, Xin, B ); + \endcode + If \c B points to a Teuchos::SerialDenseMatrix with size inconsistent with \c X, then a std::invalid_argument exception will be thrown. Otherwise, if \c B is null, the caller will not have + access to the computed coefficients. This matrix is not necessarily triangular (as in a QR factorization); see the documentation of specific orthogonalization managers.
    + In general, \c B has no non-zero structure. + + @param Q [in] A list of multivector bases specifying the subspaces to be orthogonalized against, satisfying + \f[ + \langle Q[i], Q[j] \rangle = I \quad\textrm{if}\quad i=j + \f] + and + \f[ + \langle Q[i], Q[j] \rangle = 0 \quad\textrm{if}\quad i \neq j\ . + \f] + + @return Rank of the basis computed by this method, less than or equal to the number of columns in \c X. This specifies how many columns in the returned \c X and rows in the returned \c B are valid. + + */ + int projectAndNormalizeMat ( + MV &X, + Teuchos::RCP MX = Teuchos::null, + Teuchos::Array > > C = Teuchos::tuple(Teuchos::null), + Teuchos::RCP > B = Teuchos::null, + Teuchos::Array > Q = Teuchos::tuple(Teuchos::null) ) const; + + //@} + + //! @name Error methods + //@{ + + /*! \brief This method computes the error in orthonormality of a multivector, measured + * as the Frobenius norm of the difference innerProd(X,Y) - I. + * The method has the option of exploiting a caller-provided \c MX. + */ + typename Teuchos::ScalarTraits::magnitudeType + orthonormErrorMat(const MV &X, Teuchos::RCP MX = Teuchos::null) const; + + /*! \brief This method computes the error in orthogonality of two multivectors, measured + * as the Frobenius norm of innerProd(X,Y). + * The method has the option of exploiting a caller-provided \c MX. + */ + typename Teuchos::ScalarTraits::magnitudeType + orthogErrorMat(const MV &X1, Teuchos::RCP MX1, const MV &X2) const; + + //@} + + private: + + MagnitudeType eps_; + bool debug_; + + // ! Routine to find an orthogonal/orthonormal basis for the + int findBasis( MV &X, Teuchos::RCP MX, + Teuchos::Array > > C, + Teuchos::RCP > B, + Teuchos::Array > Q, + bool normalize ) const; + }; + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Constructor + template + SVQBOrthoManager::SVQBOrthoManager( Teuchos::RCP Op, bool debug) + : MatOrthoManager(Op), dbgstr(" *** "), debug_(debug) { + + Teuchos::LAPACK lapack; + eps_ = lapack.LAMCH('E'); + if (debug_) { + std::cout << "eps_ == " << eps_ << std::endl; + } + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Compute the distance from orthonormality + template + typename Teuchos::ScalarTraits::magnitudeType + SVQBOrthoManager::orthonormErrorMat(const MV &X, Teuchos::RCP MX) const { + const ScalarType ONE = SCT::one(); + int rank = MVT::GetNumberVecs(X); + Teuchos::SerialDenseMatrix xTx(rank,rank); + innerProdMat(X,X,MX,xTx); + for (int i=0; i + typename Teuchos::ScalarTraits::magnitudeType + SVQBOrthoManager::orthogErrorMat(const MV &X1, Teuchos::RCP MX1, const MV &X2) const { + int r1 = MVT::GetNumberVecs(X1); + int r2 = MVT::GetNumberVecs(X2); + Teuchos::SerialDenseMatrix xTx(r2,r1); + innerProdMat(X2,X1,MX1,xTx); + return xTx.normFrobenius(); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Find an Op-orthonormal basis for span(X) - span(W) + template + int SVQBOrthoManager::projectAndNormalizeMat( + MV &X, Teuchos::RCP MX, + Teuchos::Array > > C, + Teuchos::RCP > B, + Teuchos::Array > Q ) const { + + return findBasis(X,MX,C,B,Q,true); + } + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Find an Op-orthonormal basis for span(X), with rank numvectors(X) + template + int SVQBOrthoManager::normalizeMat( + MV &X, Teuchos::RCP MX, + Teuchos::RCP > B ) const { + Teuchos::Array > > C; + Teuchos::Array > Q; + return findBasis(X,MX,C,B,Q,true); + } + + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + template + void SVQBOrthoManager::projectMat( + MV &X, Teuchos::RCP MX, + Teuchos::Array > > C, + Teuchos::Array > Q) const { + findBasis(X,MX,C,Teuchos::null,Q,false); + } + + + ////////////////////////////////////////////////////////////////////////////////////////////////// + // Find an Op-orthonormal basis for span(X), with the option of extending the subspace so that + // the rank is numvectors(X) + // + // Tracking the coefficients (C[i] and B) for this code is complicated by the fact that the loop + // structure looks like + // do + // project + // do + // ortho + // end + // end + // However, the recurrence for the coefficients is not complicated: + // B = I + // C = 0 + // do + // project yields newC + // C = C + newC*B + // do + // ortho yields newR + // B = newR*B + // end + // end + // This holds for each individual C[i] (which correspond to the list of bases we are orthogonalizing + // against). + // + template + int SVQBOrthoManager::findBasis( + MV &X, Teuchos::RCP MX, + Teuchos::Array > > C, + Teuchos::RCP > B, + Teuchos::Array > Q, + bool normalize) const { + + const ScalarType ONE = SCT::one(); + const MagnitudeType MONE = SCTM::one(); + const MagnitudeType ZERO = SCTM::zero(); + + int numGS = 0, + numSVQB = 0, + numRand = 0; + + // get sizes of X,MX + int xc = MVT::GetNumberVecs(X); + int xr = MVT::GetVecLength( X ); + + // get sizes of Q[i] + int nq = Q.length(); + int qr = (nq == 0) ? 0 : MVT::GetVecLength(*Q[0]); + int qsize = 0; + std::vector qcs(nq); + for (int i=0; i xr) { + // not well-posed + TEST_FOR_EXCEPTION( true, std::invalid_argument, + "Anasazi::SVQBOrthoManager::findBasis(): Orthogonalization constraints not feasible" ); + } + + // try to short-circuit as early as possible + if (normalize == false && (qsize == 0 || xc == 0)) { + // nothing to do + return 0; + } + else if (normalize == true && (xc == 0 || xr == 0)) { + // normalize requires X not empty + TEST_FOR_EXCEPTION( true, std::invalid_argument, + "Anasazi::SVQBOrthoManager::findBasis(): X must be non-empty" ); + } + + // check that Q matches X + TEST_FOR_EXCEPTION( qsize != 0 && qr != xr , std::invalid_argument, + "Anasazi::SVQBOrthoManager::findBasis(): Size of X not consistant with size of Q" ); + + /* If we don't have enough C, expanding it creates null references + * If we have too many, resizing just throws away the later ones + * If we have exactly as many as we have Q, this call has no effect + */ + C.resize(nq); + Teuchos::Array > > newC(nq); + // check the size of the C[i] against the Q[i] and consistency between Q[i] + for (int i=0; i(qcs[i],xc) ); + } + else { + TEST_FOR_EXCEPTION( C[i]->numRows() != qcs[i] || C[i]->numCols() != xc, std::invalid_argument, + "Anasazi::SVQBOrthoManager::findBasis(): Size of Q not consistant with C" ); + } + // clear C[i] + C[i]->putScalar(ZERO); + newC[i] = Teuchos::rcp( new Teuchos::SerialDenseMatrix(*C[i]) ); + } + + + //////////////////////////////////////////////////////// + // Allocate necessary storage + // C were allocated above + // Allocate MX and B (if necessary) + // Set B = I + if (normalize == true) { + if ( B == Teuchos::null ) { + B = Teuchos::rcp( new Teuchos::SerialDenseMatrix(xc,xc) ); + } + TEST_FOR_EXCEPTION( B->numRows() != xc || B->numCols() != xc, std::invalid_argument, + "Anasazi::SVQBOrthoManager::findBasis(): Size of B not consistant with X" ); + // set B to I + B->putScalar(ZERO); + for (int i=0; i workX; + if (normalize) { + workX = MVT::Clone(X,xc); + } + if (this->_hasOp) { + if (MX == Teuchos::null) { + // we need to allocate space for MX + MX = MVT::Clone(X,xc); + OPT::Apply(*(this->_Op),X,*MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + } + else { + MX = Teuchos::rcp(&X,false); + } + std::vector normX(xc), invnormX(xc); + Teuchos::SerialDenseMatrix XtMX(xc,xc), workU(1,1); + Teuchos::LAPACK lapack; + /********************************************************************** + * allocate storage for eigenvectors,eigenvalues of X^T Op X, and for + * the work space needed to compute this xc-by-xc eigendecomposition + **********************************************************************/ + std::vector work; + std::vector lambda, lambdahi, rwork; + if (normalize) { + // get size of work from ILAENV + int lwork = lapack.ILAENV(1,"hetrd","VU",xc,-1,-1,-1); + // lwork >= (nb+1)*n for complex + // lwork >= (nb+2)*n for real + TEST_FOR_EXCEPTION( lwork < 0, OrthoError, + "Anasazi::SVQBOrthoManager::findBasis(): Error code from ILAENV" ); + + lwork = (lwork+2)*xc; + work.resize(lwork); + // size of rwork is max(1,3*xc-2) + lwork = (3*xc-2 > 1) ? 3*xc - 2 : 1; + rwork.resize(lwork); + // size of lambda is xc + lambda.resize(xc); + lambdahi.resize(xc); + workU.reshape(xc,xc); + } + + // test sizes of X,MX + int mxc = (this->_hasOp) ? MVT::GetNumberVecs( *MX ) : xc; + int mxr = (this->_hasOp) ? MVT::GetVecLength( *MX ) : xr; + TEST_FOR_EXCEPTION( xc != mxc || xr != mxr, std::invalid_argument, + "Anasazi::SVQBOrthoManager::findBasis(): Size of X not consistant with MX" ); + + // sentinel to continue the outer loop (perform another projection step) + bool doGramSchmidt = true; + // variable for testing orthonorm/orthog + MagnitudeType tolerance = MONE/SCTM::squareroot(eps_); + + // outer loop + while (doGramSchmidt) { + + //////////////////////////////////////////////////////////////////////////////////// + // perform projection + if (qsize > 0) { + + numGS++; + + // Compute the norms of the vectors + normMat(X,MX,&normX); + // normalize the vectors + Teuchos::RCP Xi,MXi; + std::vector ind(1); + for (int i=0; i_hasOp) { + MXi = MVT::CloneView(*MX,ind); + MVT::MvAddMv(ZERO,*MXi,invnormX[i],*MXi,*MXi); + MXi = Teuchos::null; + } + } + // check that vectors are normalized now + if (debug_) { + std::vector nrm2(xc); + std::cout << dbgstr << "max post-scale norm: (with/without MX) : "; + MagnitudeType maxpsnw = ZERO, maxpsnwo = ZERO; + normMat(X,MX,&nrm2); + for (int i=0; i maxpsnw ? nrm2[i] : maxpsnw); + } + MatOrthoManager::norm(X,&nrm2); + for (int i=0; i maxpsnwo ? nrm2[i] : maxpsnwo); + } + std::cout << "(" << maxpsnw << "," << maxpsnwo << ")" << std::endl; + } + // project the vectors onto the Qi + for (int i=0; i_hasOp) { + OPT::Apply(*(this->_Op),X,*MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + + // + // Compute largest column norm of + // ( C[0] ) + // C = ( .... ) + // ( C[nq-1] ) + MagnitudeType maxNorm = ZERO; + for (int j=0; j maxNorm) ? sum : maxNorm; + } + + // do we perform another GS? + if (maxNorm < 0.36) { + doGramSchmidt = false; + } + + // unscale newC to reflect the scaling of X + for (int k=0; kmultiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,ONE,*newC[i],*B,ONE); + TEST_FOR_EXCEPTION(info != 0, std::logic_error, "Anasazi::SVQBOrthoManager::findBasis(): Input error to SerialDenseMatrix::multiply."); + } + } + else { + // not normalizing + for (int i=0; i= tolerance) { + + numSVQB++; + + // compute X^T Op X + innerProdMat(X,X,MX,XtMX); + + // compute scaling matrix for XtMX: D^{.5} and D^{-.5} (D-half and D-half-inv) + std::vector Dh(xc), Dhi(xc); + for (int i=0; i ind(xc); + for (int i=0; i_hasOp) { + if (maxLambda >= tolerance * minLambda) { + // explicit update of MX + OPT::Apply(*(this->_Op),X,*MX); + this->_OpCounter += MVT::GetNumberVecs(X); + } + else { + // implicit update of MX + // copy MX into workX + MVT::SetBlock(*MX,ind,*workX); + // + // compute workX * workU into MX + MVT::MvTimesMatAddMv(ONE,*workX,workU,ZERO,*MX); + } + } + + // accumulate new B into previous B + // B = Lh * U^H * Dh * B + for (int j=0; jmultiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,ONE,XtMX,workU,ZERO); + TEST_FOR_EXCEPTION(info != 0, std::logic_error, "Anasazi::SVQBOrthoManager::findBasis(): Input error to SerialDenseMatrix::multiply."); + for (int j=0; j= 0) { + if (debug_) { + std::cout << dbgstr << "augmenting multivec with " << iZeroMax+1 << " random directions" << std::endl; + } + + numRand++; + // put random info in the first iZeroMax+1 vectors of X,MX + std::vector ind(iZeroMax+1); + for (int i=0; i Xnull,MXnull; + Xnull = MVT::CloneView(X,ind); + MVT::MvRandom(*Xnull); + if (this->_hasOp) { + MXnull = MVT::CloneView(*MX,ind); + OPT::Apply(*(this->_Op),*Xnull,*MXnull); + this->_OpCounter += MVT::GetNumberVecs(*Xnull); + MXnull = Teuchos::null; + } + Xnull = Teuchos::null; + condT = tolerance; + doGramSchmidt = true; + break; // break from while(condT > tolerance) + } + + condT = SCTM::magnitude(maxLambda / minLambda); + if (debug_) { + std::cout << dbgstr << "condT: " << condT << std::endl; + } + + } // end while (condT >= tolerance) + + if ((doGramSchmidt == false) && (condT > SCTM::squareroot(tolerance))) { + doGramSchmidt = true; + } + } + // end if(normalize) + + } // end while (doGramSchmidt) + + if (debug_) { + std::cout << dbgstr << "(numGS,numSVQB,numRand) : " + << "(" << numGS + << "," << numSVQB + << "," << numRand + << ")" << std::endl; + } + + return xc; + } + +} // namespace Anasazi + +#endif // ANASAZI_SVQB_ORTHOMANAGER_HPP + diff --git a/fastlib/trilinos/include/AnasaziSimpleLOBPCGSolMgr.hpp b/fastlib/trilinos/include/AnasaziSimpleLOBPCGSolMgr.hpp new file mode 100644 index 0000000000..73cae6aa3b --- /dev/null +++ b/fastlib/trilinos/include/AnasaziSimpleLOBPCGSolMgr.hpp @@ -0,0 +1,398 @@ + +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_SIMPLE_LOBPCG_SOLMGR_HPP +#define ANASAZI_SIMPLE_LOBPCG_SOLMGR_HPP + +/*! \file AnasaziSimpleLOBPCGSolMgr.hpp + \brief The Anasazi::SimpleLOBPCGSolMgr provides a simple solver manager over the LOBPCG + eigensolver. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +#include "AnasaziEigenproblem.hpp" +#include "AnasaziSolverManager.hpp" + +#include "AnasaziLOBPCG.hpp" +#include "AnasaziBasicSort.hpp" +#include "AnasaziSVQBOrthoManager.hpp" +#include "AnasaziStatusTestMaxIters.hpp" +#include "AnasaziStatusTestResNorm.hpp" +#include "AnasaziStatusTestCombo.hpp" +#include "AnasaziStatusTestOutput.hpp" +#include "AnasaziBasicOutputManager.hpp" +#include "AnasaziSolverUtils.hpp" + +#include "Teuchos_TimeMonitor.hpp" + +/** \example LOBPCG/LOBPCGEpetraExSimple.cpp + This is an example of how to use the Anasazi::SimpleLOBPCGSolMgr solver manager. +*/ + +/*! \class Anasazi::SimpleLOBPCGSolMgr + \brief The Anasazi::SimpleLOBPCGSolMgr provides a simple solver + manager over the LOBPCG eigensolver. + + Anasazi::SimpleLOBPCGSolMgr allows the user to specify convergence + tolerance, verbosity level and block size. When block size is less than the + number of requested eigenvalues specified in the eigenproblem, checkpointing + is activated. + + The purpose of this solver manager was to provide an example of a simple + solver manager, useful for demonstration as well as a jumping-off point for + solvermanager development. Also, the solver manager is useful for testing + some of the features of the Anasazi::LOBPCG eigensolver, principally the use + of auxiliary vectors. + + This solver manager does not verify before quitting that the nev eigenvectors + that have converged are also the smallest nev eigenvectors that are known. + + \ingroup anasazi_solver_framework + + \author Chris Baker, Ulrich Hetmaniuk, Rich Lehoucq, Heidi Thornquist +*/ + +namespace Anasazi { + +template +class SimpleLOBPCGSolMgr : public SolverManager { + + private: + typedef MultiVecTraits MVT; + typedef Teuchos::ScalarTraits SCT; + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + public: + + //!@name Constructors/Destructor + //@{ + + /*! \brief Basic constructor for SimpleLOBPCGSolMgr. + * + * This constructor accepts the Eigenproblem to be solved in addition + * to a parameter list of options for the solver manager. These options include the following: + * - "Which" - a \c string specifying the desired eigenvalues: SM, LM, SR or LR. Default: SR + * - "Block Size" - a \c int specifying the block size to be used by the underlying LOBPCG solver. Default: problem->getNEV() + * - "Maximum Iterations" - a \c int specifying the maximum number of iterations the underlying solver is allowed to perform. Default: 100 + * - "Verbosity" - a sum of MsgType specifying the verbosity. Default: Anasazi::Errors + * - "Convergence Tolerance" - a \c MagnitudeType specifying the level that residual norms must reach to decide convergence. Default: machine precision + */ + SimpleLOBPCGSolMgr( const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ); + + //! Destructor. + virtual ~SimpleLOBPCGSolMgr() {}; + //@} + + //! @name Accessor methods + //@{ + + const Eigenproblem& getProblem() const { + return *problem_; + } + + //@} + + //! @name Solver application methods + //@{ + + /*! \brief This method performs possibly repeated calls to the underlying eigensolver's iterate() routine + * until the problem has been solved (as decided by the solver manager) or the solver manager decides to + * quit. + * + * \returns ::ReturnType specifying: + * - ::Converged: the eigenproblem was solved to the specification required by the solver manager. + * - ::Unconverged: the eigenproblem was not solved to the specification desired by the solver manager + */ + ReturnType solve(); + //@} + + private: + Teuchos::RCP > problem_; + std::string whch_; + MagnitudeType tol_; + int verb_; + int blockSize_; + int maxIters_; +}; + + +//////////////////////////////////////////////////////////////////////////////////////// +template +SimpleLOBPCGSolMgr::SimpleLOBPCGSolMgr( + const Teuchos::RCP > &problem, + Teuchos::ParameterList &pl ) : + problem_(problem), + whch_("LM"), + tol_(1e-6), + verb_(Anasazi::Errors), + blockSize_(0), + maxIters_(100) +{ + TEST_FOR_EXCEPTION(problem_ == Teuchos::null, std::invalid_argument, "Problem not given to solver manager."); + TEST_FOR_EXCEPTION(!problem_->isProblemSet(), std::invalid_argument, "Problem not set."); + TEST_FOR_EXCEPTION(!problem_->isHermitian(), std::invalid_argument, "Problem not symmetric."); + TEST_FOR_EXCEPTION(problem_->getInitVec() == Teuchos::null,std::invalid_argument, "Problem does not contain initial vectors to clone from."); + + whch_ = pl.get("Which","SR"); + TEST_FOR_EXCEPTION(whch_ != "SM" && whch_ != "LM" && whch_ != "SR" && whch_ != "LR", + AnasaziError, + "SimpleLOBPCGSolMgr: \"Which\" parameter must be SM, LM, SR or LR."); + + tol_ = pl.get("Convergence Tolerance",tol_); + TEST_FOR_EXCEPTION(tol_ <= 0, + AnasaziError, + "SimpleLOBPCGSolMgr: \"Tolerance\" parameter must be strictly postiive."); + + // verbosity level + if (pl.isParameter("Verbosity")) { + if (Teuchos::isParameterType(pl,"Verbosity")) { + verb_ = pl.get("Verbosity", verb_); + } else { + verb_ = (int)Teuchos::getParameter(pl,"Verbosity"); + } + } + + + blockSize_= pl.get("Block Size",problem_->getNEV()); + TEST_FOR_EXCEPTION(blockSize_ <= 0, + AnasaziError, + "SimpleLOBPCGSolMgr: \"Block Size\" parameter must be strictly positive."); + + maxIters_ = pl.get("Maximum Iterations",maxIters_); +} + + + +//////////////////////////////////////////////////////////////////////////////////////// +template +ReturnType +SimpleLOBPCGSolMgr::solve() { + + // sort manager + Teuchos::RCP > sorter = Teuchos::rcp( new BasicSort(whch_) ); + // output manager + Teuchos::RCP > printer = Teuchos::rcp( new BasicOutputManager(verb_) ); + // status tests + Teuchos::RCP > max; + if (maxIters_ > 0) { + max = Teuchos::rcp( new StatusTestMaxIters(maxIters_) ); + } + else { + max = Teuchos::null; + } + Teuchos::RCP > norm + = Teuchos::rcp( new StatusTestResNorm(tol_) ); + Teuchos::Array< Teuchos::RCP > > alltests; + alltests.push_back(norm); + if (max != Teuchos::null) alltests.push_back(max); + Teuchos::RCP > combo + = Teuchos::rcp( new StatusTestCombo( + StatusTestCombo::OR, alltests + )); + // printing StatusTest + Teuchos::RCP > outputtest + = Teuchos::rcp( new StatusTestOutput( printer,combo,1,Passed ) ); + // orthomanager + Teuchos::RCP > ortho + = Teuchos::rcp( new SVQBOrthoManager(problem_->getM()) ); + // parameter list + Teuchos::ParameterList plist; + plist.set("Block Size",blockSize_); + plist.set("Full Ortho",true); + + // create an LOBPCG solver + Teuchos::RCP > lobpcg_solver + = Teuchos::rcp( new LOBPCG(problem_,sorter,printer,outputtest,ortho,plist) ); + // add the auxillary vecs from the eigenproblem to the solver + if (problem_->getAuxVecs() != Teuchos::null) { + lobpcg_solver->setAuxVecs( Teuchos::tuple >(problem_->getAuxVecs()) ); + } + + int numfound = 0; + int nev = problem_->getNEV(); + Teuchos::Array< Teuchos::RCP > foundvecs; + Teuchos::Array< Teuchos::RCP< std::vector > > foundvals; + while (numfound < nev) { + // reduce the strain on norm test, if we are almost done + if (nev - numfound < blockSize_) { + norm->setQuorum(nev-numfound); + } + + // tell the solver to iterate + try { + lobpcg_solver->iterate(); + } + catch (std::exception e) { + // we are a simple solver manager. we don't catch exceptions. set solution empty, then rethrow. + printer->stream(Anasazi::Errors) << "Exception: " << e.what() << std::endl; + Eigensolution sol; + sol.numVecs = 0; + problem_->setSolution(sol); + throw; + } + + // check the status tests + if (norm->getStatus() == Passed) { + + int num = norm->howMany(); + // if num < blockSize_, it is because we are on the last iteration: num+numfound>=nev + TEST_FOR_EXCEPTION(num < blockSize_ && num+numfound < nev, + std::logic_error, + "Anasazi::SimpleLOBPCGSolMgr::solve(): logic error."); + std::vector ind = norm->whichVecs(); + // just grab the ones that we need + if (num + numfound > nev) { + num = nev - numfound; + ind.resize(num); + } + + // copy the converged eigenvectors + Teuchos::RCP newvecs = MVT::CloneCopy(*lobpcg_solver->getRitzVectors(),ind); + // store them + foundvecs.push_back(newvecs); + // add them as auxiliary vectors + Teuchos::Array > auxvecs = lobpcg_solver->getAuxVecs(); + auxvecs.push_back(newvecs); + // setAuxVecs() will reset the solver to uninitialized, without messing with numIters() + lobpcg_solver->setAuxVecs(auxvecs); + + // copy the converged eigenvalues + Teuchos::RCP > newvals = Teuchos::rcp( new std::vector(num) ); + std::vector > all = lobpcg_solver->getRitzValues(); + for (int i=0; igetStatus() == Passed) { + + int num = norm->howMany(); + std::vector ind = norm->whichVecs(); + + if (num > 0) { + // copy the converged eigenvectors + Teuchos::RCP newvecs = MVT::CloneCopy(*lobpcg_solver->getRitzVectors(),ind); + // orthornormalize to be safe + ortho->normalizeMat(*newvecs,Teuchos::null,Teuchos::null); + // store them + foundvecs.push_back(newvecs); + // don't bother adding them as auxiliary vectors; we have reached maxiters and are going to quit + + // copy the converged eigenvalues + Teuchos::RCP > newvals = Teuchos::rcp( new std::vector(num) ); + std::vector > all = lobpcg_solver->getRitzValues(); + for (int i=0; i sol; + sol.numVecs = numfound; + if (numfound > 0) { + // allocate space for eigenvectors + sol.Evecs = MVT::Clone(*problem_->getInitVec(),numfound); + } + else { + sol.Evecs = Teuchos::null; + } + sol.Espace = sol.Evecs; + // allocate space for eigenvalues + std::vector vals(numfound); + sol.Evals.resize(numfound); + // all real eigenvalues: set index vectors [0,...,numfound-1] + sol.index.resize(numfound,0); + // store eigenvectors, eigenvalues + int curttl = 0; + for (unsigned int i=0; isize()) != MVT::GetNumberVecs(*foundvecs[i]), std::logic_error, "Anasazi::SimpleLOBPCGSolMgr::solve(): inconsistent sizes"); + unsigned int lclnum = foundvals[i]->size(); + std::vector lclind(lclnum); + for (unsigned int j=0; jbegin(), foundvals[i]->end(), vals.begin()+curttl ); + + curttl += lclnum; + } + TEST_FOR_EXCEPTION( curttl != sol.numVecs, std::logic_error, "Anasazi::SimpleLOBPCGSolMgr::solve(): inconsistent sizes"); + + // sort the eigenvalues and permute the eigenvectors appropriately + if (numfound > 0) { + std::vector order(sol.numVecs); + sorter->sort( lobpcg_solver.get(), sol.numVecs, vals, &order ); + // store the values in the Eigensolution + for (int i=0; i msutils; + msutils.permuteVectors(sol.numVecs,order,*sol.Evecs); + } + + // print final summary + lobpcg_solver->currentStatus(printer->stream(FinalSummary)); + + // print timing information + Teuchos::TimeMonitor::summarize(printer->stream(TimingDetails)); + + // send the solution to the eigenproblem + problem_->setSolution(sol); + printer->stream(Debug) << "Returning " << sol.numVecs << " eigenpairs to eigenproblem." << std::endl; + + // return from SolMgr::solve() + if (sol.numVecs < nev) return Unconverged; + return Converged; +} + + + + +} // end Anasazi namespace + +#endif /* ANASAZI_SIMPLE_LOBPCG_SOLMGR_HPP */ diff --git a/fastlib/trilinos/include/AnasaziSolverManager.hpp b/fastlib/trilinos/include/AnasaziSolverManager.hpp new file mode 100644 index 0000000000..d7b918fdb5 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziSolverManager.hpp @@ -0,0 +1,90 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_SOLVERMANAGER_HPP +#define ANASAZI_SOLVERMANAGER_HPP + +/*! \file AnasaziSolverManager.hpp + \brief Pure virtual base class which describes the basic interface for a solver manager. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "AnasaziEigenproblem.hpp" + +#include "Teuchos_ParameterList.hpp" +#include "Teuchos_RCP.hpp" + +/*! \class Anasazi::SolverManager + \brief The Anasazi::SolverManager is a templated virtual base class that defines the + basic interface that any solver manager will support. +*/ + +namespace Anasazi { + +template +class SolverManager { + + public: + + //!@name Constructors/Destructor + //@{ + + //! Empty constructor. + SolverManager() {}; + + //! Destructor. + virtual ~SolverManager() {}; + //@} + + //! @name Accessor methods + //@{ + + virtual const Eigenproblem& getProblem() const = 0; + + //@} + + //! @name Solver application methods + //@{ + + /*! \brief This method performs possibly repeated calls to the underlying eigensolver's iterate() routine + * until the problem has been solved (as decided by the solver manager) or the solver manager decides to + * quit. + * + * \returns ::ReturnType specifying: + * - ::Converged: the eigenproblem was solved to the specification required by the solver manager. + * - ::Unconverged: the eigenproblem was not solved to the specification desired by the solver manager + */ + virtual ReturnType solve() = 0; + //@} + +}; + +} // end Anasazi namespace + +#endif /* ANASAZI_SOLVERMANAGER_HPP */ diff --git a/fastlib/trilinos/include/AnasaziSolverUtils.hpp b/fastlib/trilinos/include/AnasaziSolverUtils.hpp new file mode 100644 index 0000000000..036089bbd5 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziSolverUtils.hpp @@ -0,0 +1,680 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_SOLVER_UTILS_HPP +#define ANASAZI_SOLVER_UTILS_HPP + +/*! \file AnasaziSolverUtils.hpp + \brief Class which provides internal utilities for the Anasazi solvers. +*/ + +/*! \class Anasazi::SolverUtils + \brief Anasazi's templated, static class providing utilities for + the solvers. + + This class provides concrete, templated implementations of utilities necessary + for the solvers. These utilities include + sorting, orthogonalization, projecting/solving local eigensystems, and sanity + checking. These are internal utilties, so the user should not alter this class. + + \author Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziMultiVecTraits.hpp" +#include "AnasaziOperatorTraits.hpp" +#include "Teuchos_ScalarTraits.hpp" + +#include "AnasaziOutputManager.hpp" +#include "Teuchos_BLAS.hpp" +#include "Teuchos_LAPACK.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" + +namespace Anasazi { + + template + class SolverUtils + { + public: + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef typename Teuchos::ScalarTraits SCT; + + //! @name Constructor/Destructor + //@{ + + //! Constructor. + SolverUtils(); + + //! Destructor. + virtual ~SolverUtils() {}; + + //@} + + //! @name Sorting Methods + //@{ + + //! Permute the vectors in a multivector according to the permutation vector \c perm, and optionally the residual vector \c resids + static void permuteVectors(const int n, const std::vector &perm, MV &Q, std::vector< typename Teuchos::ScalarTraits::magnitudeType >* resids = 0); + + //! Permute the columns of a Teuchos::SerialDenseMatrix according to the permutation vector \c perm + static void permuteVectors(const std::vector &perm, Teuchos::SerialDenseMatrix &Q); + + //@} + + //! @name Basis update methods + //@{ + + //! Apply a sequence of Householder reflectors (from \c GEQRF) to a multivector, using minimal workspace. + /*! + @param k [in] the number of Householder reflectors composing the product + @param V [in/out] the multivector to be modified, with \f$n\f$ columns + @param H [in] a \f$n \times k\f$ matrix containing the encoded Householder vectors, as returned from \c GEQRF (see below) + @param tau [in] the \f$n\f$ coefficients for the Householder reflects, as returned from \c GEQRF + @param workMV [work] (optional) a multivector used for workspace. it need contain only a single vector; it if contains more, only the first vector will be modified. + + This routine applies a sequence of Householder reflectors, \f$H_1 H_2 \cdots H_k\f$, to a multivector \f$V\f$. The + reflectors are applied individually, as rank-one updates to the multivector. The benefit of this is that the only + required workspace is a one-column multivector. This workspace can be provided by the user. If it is not, it will + be allocated locally on each call to applyHouse. + + Each \f$H_i\f$ (\f$i=1,\ldots,k \leq n\f$) has the form
    + \f$ H_i = I - \tau_i v_i v_i^T \f$
    + where \f$\tau_i\f$ is a scalar and \f$v_i\f$ is a vector with + \f$v_i(1:i-1) = 0\f$ and \f$e_i^T v_i = 1\f$; \f$v(i+1:n)\f$ is stored below H(i,i) + and \f$\tau_i\f$ in tau[i-1]. (Note: zero-based indexing used for data structures \c H and \c tau, while one-based indexing used for mathematic object \f$v_i\f$). + + If the multivector is \f$m \times n\f$ and we apply \f$k\f$ Householder reflectors, the total cost of the method is + \f$4mnk - 2m(k^2-k)\f$ flops. For \f$k=n\f$, this becomes \f$2mn^2\f$, the same as for a matrix-matrix multiplication by the accumulated Householder reflectors. + */ + static void applyHouse(int k, MV &V, const Teuchos::SerialDenseMatrix &H, const std::vector &tau, Teuchos::RCP workMV = Teuchos::null); + + //@} + + //! @name Eigensolver Projection Methods + //@{ + + //! Routine for computing the first NEV generalized eigenpairs of the Hermitian pencil (KK, MM) + /*! + @param size [in] Dimension of the eigenproblem (KK, MM) + @param KK [in] Hermitian "stiffness" matrix + @param MM [in] Hermitian positive-definite "mass" matrix + @param EV [in] Dense matrix to store the nev eigenvectors + @param theta [in] Array to store the eigenvalues (Size = nev ) + @param nev [in/out] Number of the smallest eigenvalues requested (in) / computed (out) + @param esType [in] Flag to select the algorithm +
      +
    • esType = 0 (default) Uses LAPACK routine (Cholesky factorization of MM) + with deflation of MM to get orthonormality of + eigenvectors (\f$S^TMMS = I\f$) +
    • esType = 1 Uses LAPACK routine (Cholesky factorization of MM) + (no check of orthonormality) +
    • esType = 10 Uses LAPACK routine for simple eigenproblem on KK + (MM is not referenced in this case) +
    + + \note The code accesses only the upper triangular part of KK and MM. + \return Integer \c info on the status of the computation + // Return the integer info on the status of the computation +
      +
    • info = 0 >> Success +
    • info = - 20 >> Failure in LAPACK routine +
    + */ + static int directSolver(int size, const Teuchos::SerialDenseMatrix &KK, + Teuchos::RCP > MM, + Teuchos::SerialDenseMatrix &EV, + std::vector< typename Teuchos::ScalarTraits::magnitudeType > &theta, + int &nev, int esType = 0); + //@} + + //! @name Sanity Checking Methods + //@{ + + //! Return the maximum coefficient of the matrix \f$M * X - MX\f$ scaled by the maximum coefficient of \c MX. + /*! \note When \c M is not specified, the identity is used. + */ + static typename Teuchos::ScalarTraits::magnitudeType errorEquality(const MV &X, const MV &MX, Teuchos::RCP M = Teuchos::null); + + //@} + + private: + + //! @name Internal Typedefs + //@{ + + typedef MultiVecTraits MVT; + typedef OperatorTraits OPT; + + //@} + }; + + //----------------------------------------------------------------------------- + // + // CONSTRUCTOR + // + //----------------------------------------------------------------------------- + + template + SolverUtils::SolverUtils() {} + + + //----------------------------------------------------------------------------- + // + // SORTING METHODS + // + //----------------------------------------------------------------------------- + + ////////////////////////////////////////////////////////////////////////// + // permuteVectors for MV + template + void SolverUtils::permuteVectors( + const int n, + const std::vector &perm, + MV &Q, + std::vector< typename Teuchos::ScalarTraits::magnitudeType >* resids) + { + // Permute the vectors according to the permutation vector \c perm, and + // optionally the residual vector \c resids + + int i, j; + std::vector permcopy(perm), swapvec(n-1); + std::vector index(1); + ScalarType one = Teuchos::ScalarTraits::one(); + ScalarType zero = Teuchos::ScalarTraits::zero(); + + TEST_FOR_EXCEPTION(n > MVT::GetNumberVecs(Q), std::invalid_argument, "Anasazi::SolverUtils::permuteVectors(): argument n larger than width of input multivector."); + + // We want to recover the elementary permutations (individual swaps) + // from the permutation vector. Do this by constructing the inverse + // of the permutation, by sorting them to {1,2,...,n}, and recording + // the elementary permutations of the inverse. + for (i=0; i( permcopy[j], permcopy[i] ); + + swapvec[i] = j; + } + + // now apply the elementary permutations of the inverse in reverse order + for (i=n-2; i>=0; i--) { + j = swapvec[i]; + // + // Swap (i,j) + // + // Swap residuals (if they exist) + if (resids) { + std::swap( (*resids)[i], (*resids)[j] ); + } + // + // Swap corresponding vectors + index[0] = j; + Teuchos::RCP tmpQ = MVT::CloneCopy( Q, index ); + Teuchos::RCP tmpQj = MVT::CloneView( Q, index ); + index[0] = i; + Teuchos::RCP tmpQi = MVT::CloneView( Q, index ); + MVT::MvAddMv( one, *tmpQi, zero, *tmpQi, *tmpQj ); + MVT::MvAddMv( one, *tmpQ, zero, *tmpQ, *tmpQi ); + } + } + + + ////////////////////////////////////////////////////////////////////////// + // permuteVectors for MV + template + void SolverUtils::permuteVectors( + const std::vector &perm, + Teuchos::SerialDenseMatrix &Q) + { + // Permute the vectors in Q according to the permutation vector \c perm, and + // optionally the residual vector \c resids + Teuchos::BLAS blas; + const int n = perm.size(); + const int m = Q.numRows(); + + TEST_FOR_EXCEPTION(n != Q.numCols(), std::invalid_argument, "Anasazi::SolverUtils::permuteVectors(): size of permutation vector not equal to number of columns."); + + // Sort the primitive ritz vectors + Teuchos::SerialDenseMatrix copyQ( Q ); + for (int i=0; i + void SolverUtils::applyHouse(int k, MV &V, const Teuchos::SerialDenseMatrix &H, const std::vector &tau, Teuchos::RCP workMV) { + + const int n = MVT::GetNumberVecs(V); + const ScalarType ONE = SCT::one(); + const ScalarType ZERO = SCT::zero(); + + // early exit if V has zero-size or if k==0 + if (MVT::GetNumberVecs(V) == 0 || MVT::GetVecLength(V) == 0 || k == 0) { + return; + } + + if (workMV == Teuchos::null) { + // user did not give us any workspace; allocate some + workMV = MVT::Clone(V,1); + } + else if (MVT::GetNumberVecs(*workMV) > 1) { + std::vector first(1); + first[0] = 0; + workMV = MVT::CloneView(*workMV,first); + } + else { + TEST_FOR_EXCEPTION(MVT::GetNumberVecs(*workMV) < 1,std::invalid_argument,"Anasazi::SolverUtils::applyHouse(): work multivector was empty."); + } + // Q = H_1 ... H_k is square, with as many rows as V has vectors + // however, H need only have k columns, one each for the k reflectors. + TEST_FOR_EXCEPTION( H.numCols() != k, std::invalid_argument,"Anasazi::SolverUtils::applyHouse(): H must have at least k columns."); + TEST_FOR_EXCEPTION( (int)tau.size() != k, std::invalid_argument,"Anasazi::SolverUtils::applyHouse(): tau must have at least k entries."); + TEST_FOR_EXCEPTION( H.numRows() != MVT::GetNumberVecs(V), std::invalid_argument,"Anasazi::SolverUtils::applyHouse(): Size of H,V are inconsistent."); + + // perform the loop + // flops: Sum_{i=0:k-1} 4 m (n-i) == 4mnk - 2m(k^2- k) + for (int i=0; i activeind(n-i); + for (int j=0; j actV = MVT::CloneView(V,activeind); + + // note, below H_i, v_i and tau_i are mathematical objects which use 1-based indexing + // while H, v and tau are data structures using 0-based indexing + + // get v_i+1: i-th column of H + Teuchos::SerialDenseMatrix v(Teuchos::Copy,H,n-i,1,i,i); + // v_i+1(1:i) = 0: this isn't part of v + // e_i+1^T v_i+1 = 1 = v(0) + v(0,0) = ONE; + + // compute -tau_i V v_i + // tau_i+1 is tau[i] + // flops: 2 m n-i + MVT::MvTimesMatAddMv(-tau[i],*actV,v,ZERO,*workMV); + + // perform V = V + workMV v_i^T + // flops: 2 m n-i + Teuchos::SerialDenseMatrix vT(v,Teuchos::CONJ_TRANS); + MVT::MvTimesMatAddMv(ONE,*workMV,vT,ONE,*actV); + + actV = Teuchos::null; + } + } + + + //----------------------------------------------------------------------------- + // + // EIGENSOLVER PROJECTION METHODS + // + //----------------------------------------------------------------------------- + + template + int SolverUtils::directSolver( + int size, + const Teuchos::SerialDenseMatrix &KK, + Teuchos::RCP > MM, + Teuchos::SerialDenseMatrix &EV, + std::vector< typename Teuchos::ScalarTraits::magnitudeType > &theta, + int &nev, int esType) + { + // Routine for computing the first NEV generalized eigenpairs of the symmetric pencil (KK, MM) + // + // Parameter variables: + // + // size : Dimension of the eigenproblem (KK, MM) + // + // KK : Hermitian "stiffness" matrix + // + // MM : Hermitian positive-definite "mass" matrix + // + // EV : Matrix to store the nev eigenvectors + // + // theta : Array to store the eigenvalues (Size = nev ) + // + // nev : Number of the smallest eigenvalues requested (input) + // Number of the smallest computed eigenvalues (output) + // Routine may compute and return more or less eigenvalues than requested. + // + // esType : Flag to select the algorithm + // + // esType = 0 (default) Uses LAPACK routine (Cholesky factorization of MM) + // with deflation of MM to get orthonormality of + // eigenvectors (S^T MM S = I) + // + // esType = 1 Uses LAPACK routine (Cholesky factorization of MM) + // (no check of orthonormality) + // + // esType = 10 Uses LAPACK routine for simple eigenproblem on KK + // (MM is not referenced in this case) + // + // Note: The code accesses only the upper triangular part of KK and MM. + // + // Return the integer info on the status of the computation + // + // info = 0 >> Success + // + // info < 0 >> error in the info-th argument + // info = - 20 >> Failure in LAPACK routine + + // Define local arrays + + // Create blas/lapack objects. + Teuchos::LAPACK lapack; + Teuchos::BLAS blas; + + int rank = 0; + int info = 0; + + if (size < nev || size < 0) { + return -1; + } + if (KK.numCols() < size || KK.numRows() < size) { + return -2; + } + if ((esType == 0 || esType == 1)) { + if (MM == Teuchos::null) { + return -3; + } + else if (MM->numCols() < size || MM->numRows() < size) { + return -3; + } + } + if (EV.numCols() < size || EV.numRows() < size) { + return -4; + } + if (theta.size() < (unsigned int) size) { + return -5; + } + if (nev <= 0) { + return -6; + } + + // Query LAPACK for the "optimal" block size for HEGV + std::string lapack_name = "hetrd"; + std::string lapack_opts = "u"; + int NB = lapack.ILAENV(1, lapack_name, lapack_opts, size, -1, -1, -1); + int lwork = size*(NB+1); + std::vector work(lwork); + std::vector rwork(3*size-2); + // tt contains the eigenvalues from HEGV, which are necessarily real, and + // HEGV expects this vector to be real as well + std::vector tt( size ); + typedef typename std::vector::iterator MTIter; + + MagnitudeType tol = SCT::magnitude(SCT::squareroot(SCT::eps())); + // MagnitudeType tol = 1e-12; + ScalarType zero = Teuchos::ScalarTraits::zero(); + ScalarType one = Teuchos::ScalarTraits::one(); + + Teuchos::RCP > KKcopy, MMcopy; + Teuchos::RCP > U; + + switch (esType) { + default: + case 0: + // + // Use LAPACK to compute the generalized eigenvectors + // + for (rank = size; rank > 0; --rank) { + + U = Teuchos::rcp( new Teuchos::SerialDenseMatrix(rank,rank) ); + // + // Copy KK & MM + // + KKcopy = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, KK, rank, rank ) ); + MMcopy = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, *MM, rank, rank ) ); + // + // Solve the generalized eigenproblem with LAPACK + // + info = 0; + lapack.HEGV(1, 'V', 'U', rank, KKcopy->values(), KKcopy->stride(), + MMcopy->values(), MMcopy->stride(), &tt[0], &work[0], lwork, + &rwork[0], &info); + // + // Treat error messages + // + if (info < 0) { + std::cerr << std::endl; + std::cerr << "Anasazi::SolverUtils::directSolver(): In HEGV, argument " << -info << "has an illegal value.\n"; + std::cerr << std::endl; + return -20; + } + if (info > 0) { + if (info > rank) + rank = info - rank; + continue; + } + // + // Check the quality of eigenvectors ( using mass-orthonormality ) + // + MMcopy = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, *MM, rank, rank ) ); + for (int i = 0; i < rank; ++i) { + for (int j = 0; j < i; ++j) { + (*MMcopy)(i,j) = SCT::conjugate((*MM)(j,i)); + } + } + // U = 0*U + 1*MMcopy*KKcopy = MMcopy * KKcopy + TEST_FOR_EXCEPTION( + U->multiply(Teuchos::NO_TRANS,Teuchos::NO_TRANS,one,*MMcopy,*KKcopy,zero) != 0, + std::logic_error, "Anasazi::SolverUtils::directSolver() call to Teuchos::SerialDenseMatrix::multiply() returned an error."); + // MMcopy = 0*MMcopy + 1*KKcopy^H*U = KKcopy^H * MMcopy * KKcopy + TEST_FOR_EXCEPTION( + MMcopy->multiply(Teuchos::CONJ_TRANS,Teuchos::NO_TRANS,one,*KKcopy,*U,zero) != 0, + std::logic_error, "Anasazi::SolverUtils::directSolver() call to Teuchos::SerialDenseMatrix::multiply() returned an error."); + MagnitudeType maxNorm = SCT::magnitude(zero); + MagnitudeType maxOrth = SCT::magnitude(zero); + for (int i = 0; i < rank; ++i) { + for (int j = i; j < rank; ++j) { + if (j == i) + maxNorm = SCT::magnitude((*MMcopy)(i,j) - one) > maxNorm + ? SCT::magnitude((*MMcopy)(i,j) - one) : maxNorm; + else + maxOrth = SCT::magnitude((*MMcopy)(i,j)) > maxOrth + ? SCT::magnitude((*MMcopy)(i,j)) : maxOrth; + } + } + /* if (verbose > 4) { + std::cout << " >> Local eigensolve >> Size: " << rank; + std::cout.precision(2); + std::cout.setf(std::ios::scientific, std::ios::floatfield); + std::cout << " Normalization error: " << maxNorm; + std::cout << " Orthogonality error: " << maxOrth; + std::cout << endl; + }*/ + if ((maxNorm <= tol) && (maxOrth <= tol)) { + break; + } + } // for (rank = size; rank > 0; --rank) + // + // Copy the computed eigenvectors and eigenvalues + // ( they may be less than the number requested because of deflation ) + // + // std::cout << "directSolve rank: " << rank << "\tsize: " << size << endl; + nev = (rank < nev) ? rank : nev; + EV.putScalar( zero ); + std::copy(tt.begin(),tt.begin()+nev,theta.begin()); + for (int i = 0; i < nev; ++i) { + blas.COPY( rank, (*KKcopy)[i], 1, EV[i], 1 ); + } + break; + + case 1: + // + // Use the Cholesky factorization of MM to compute the generalized eigenvectors + // + // Copy KK & MM + // + KKcopy = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, KK, size, size ) ); + MMcopy = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, *MM, size, size ) ); + // + // Solve the generalized eigenproblem with LAPACK + // + info = 0; + lapack.HEGV(1, 'V', 'U', size, KKcopy->values(), KKcopy->stride(), + MMcopy->values(), MMcopy->stride(), &tt[0], &work[0], lwork, + &rwork[0], &info); + // + // Treat error messages + // + if (info < 0) { + std::cerr << std::endl; + std::cerr << "Anasazi::SolverUtils::directSolver(): In HEGV, argument " << -info << "has an illegal value.\n"; + std::cerr << std::endl; + return -20; + } + if (info > 0) { + if (info > size) + nev = 0; + else { + std::cerr << std::endl; + std::cerr << "Anasazi::SolverUtils::directSolver(): In HEGV, DPOTRF or DHEEV returned an error code (" << info << ").\n"; + std::cerr << std::endl; + return -20; + } + } + // + // Copy the eigenvectors and eigenvalues + // + std::copy(tt.begin(),tt.begin()+nev,theta.begin()); + for (int i = 0; i < nev; ++i) { + blas.COPY( size, (*KKcopy)[i], 1, EV[i], 1 ); + } + break; + + case 10: + // + // Simple eigenproblem + // + // Copy KK + // + KKcopy = Teuchos::rcp( new Teuchos::SerialDenseMatrix( Teuchos::Copy, KK, size, size ) ); + // + // Solve the generalized eigenproblem with LAPACK + // + lapack.HEEV('V', 'U', size, KKcopy->values(), KKcopy->stride(), &tt[0], &work[0], lwork, &rwork[0], &info); + // + // Treat error messages + if (info != 0) { + std::cerr << std::endl; + if (info < 0) + std::cerr << "Anasazi::SolverUtils::directSolver(): In DHEEV, argument " << -info << " has an illegal value\n"; + else + std::cerr << "Anasazi::SolverUtils::directSolver(): In DHEEV, the algorithm failed to converge (" << info << ").\n"; + std::cerr << std::endl; + info = -20; + break; + } + // + // Copy the eigenvectors + // + std::copy(tt.begin(),tt.begin()+nev,theta.begin()); + for (int i = 0; i < nev; ++i) { + blas.COPY( size, (*KKcopy)[i], 1, EV[i], 1 ); + } + break; + } + + return info; + } + + + //----------------------------------------------------------------------------- + // + // SANITY CHECKING METHODS + // + //----------------------------------------------------------------------------- + + template + typename Teuchos::ScalarTraits::magnitudeType + SolverUtils::errorEquality(const MV &X, const MV &MX, Teuchos::RCP M) + { + // Return the maximum coefficient of the matrix M * X - MX + // scaled by the maximum coefficient of MX. + // When M is not specified, the identity is used. + + MagnitudeType maxDiff = SCT::magnitude(SCT::zero()); + + int xc = MVT::GetNumberVecs(X); + int mxc = MVT::GetNumberVecs(MX); + + TEST_FOR_EXCEPTION(xc != mxc,std::invalid_argument,"Anasazi::SolverUtils::errorEquality(): input multivecs have different number of columns."); + if (xc == 0) { + return maxDiff; + } + + MagnitudeType maxCoeffX = SCT::magnitude(SCT::zero()); + std::vector tmp( xc ); + MVT::MvNorm(MX, &tmp); + + for (int i = 0; i < xc; ++i) { + maxCoeffX = (tmp[i] > maxCoeffX) ? tmp[i] : maxCoeffX; + } + + std::vector index( 1 ); + Teuchos::RCP MtimesX; + if (M != Teuchos::null) { + MtimesX = MVT::Clone( X, xc ); + OPT::Apply( *M, X, *MtimesX ); + } + else { + MtimesX = MVT::CloneCopy(X); + } + MVT::MvAddMv( -1.0, MX, 1.0, *MtimesX, *MtimesX ); + MVT::MvNorm( *MtimesX, &tmp ); + + for (int i = 0; i < xc; ++i) { + maxDiff = (tmp[i] > maxDiff) ? tmp[i] : maxDiff; + } + + return (maxCoeffX == 0.0) ? maxDiff : maxDiff/maxCoeffX; + + } + +} // end namespace Anasazi + +#endif // ANASAZI_SOLVER_UTILS_HPP + diff --git a/fastlib/trilinos/include/AnasaziSortManager.hpp b/fastlib/trilinos/include/AnasaziSortManager.hpp new file mode 100644 index 0000000000..47b80b4fa1 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziSortManager.hpp @@ -0,0 +1,118 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef ANASAZI_SORTMANAGER_HPP +#define ANASAZI_SORTMANAGER_HPP + +/*! \file AnasaziSortManager.hpp + \brief Virtual base class which defines the interface between an eigensolver and a class whose + job is the sorting of the computed eigenvalues +*/ + +/*! \class Anasazi::SortManager + \brief Anasazi's templated pure virtual class for managing the sorting of + approximate eigenvalues computed by the eigensolver. + + A concrete implementation of this class is necessary. The user can create + their own implementation if those supplied are not suitable for their needs. + + \author Ulrich Hetmaniuk, Rich Lehoucq, and Heidi Thornquist +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" +#include "Teuchos_TestForException.hpp" + + + +namespace Anasazi { + + //! @name LOBPCG Exceptions + //@{ + /** \brief SortManagerError is thrown when the Anasazi::SortManager is unable to sort the numbers, + * due to some failure of the sort method or error in calling it. + */ + class SortManagerError : public AnasaziError + {public: SortManagerError(const std::string& what_arg) : AnasaziError(what_arg) {}}; + + //@} + + template + class Eigensolver; + + template + class SortManager { + + public: + + //! Default Constructor + SortManager() {}; + + //! Destructor + virtual ~SortManager() {}; + + //! Sort the vector of eigenvalues, optionally returning the permutation vector. + /** + @param solver [in] Eigensolver that is calling the sorting routine + + @param n [in] Number of values in evals to be sorted. + + @param evals [in/out] Vector of length n containing the eigenvalues to be sorted + + @param perm [out] Vector of length n to store the permutation index (optional) + */ + virtual void sort(Eigensolver* solver, const int n, std::vector::magnitudeType> &evals, std::vector *perm = 0) const = 0; + + /*! \brief Sort the vectors of eigenpairs, optionally returning the permutation vector. + + This routine takes two vectors, one for each part of a complex + eigenvalue. This is helpful for solving real, non-symmetric eigenvalue + problems. + + @param solver [in] Eigensolver that is calling the sorting routine + + @param n [in] Number of values in r_evals,i_evals to be sorted. + + @param r_evals [in/out] Vector of length n containing the real part of the eigenvalues to be sorted + + @param i_evals [in/out] Vector of length n containing the imaginary part of the eigenvalues to be sorted + + @param perm [out] Vector of length n to store the permutation index (optional) + */ + virtual void sort(Eigensolver* solver, + const int n, + std::vector::magnitudeType> &r_evals, + std::vector::magnitudeType> &i_evals, + std::vector *perm = 0) const = 0; + + }; + +} + +#endif // ANASAZI_SORTMANAGER_HPP + diff --git a/fastlib/trilinos/include/AnasaziStatusTest.hpp b/fastlib/trilinos/include/AnasaziStatusTest.hpp new file mode 100644 index 0000000000..e711f09c07 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziStatusTest.hpp @@ -0,0 +1,116 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// + +#ifndef ANASAZI_STATUS_TEST_HPP +#define ANASAZI_STATUS_TEST_HPP + +/*! + \file AnasaziStatusTest.hpp + \brief Pure virtual base class for defining the status testing capabilities of Anasazi. +*/ + + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +#include "AnasaziStatusTestDecl.hpp" +#include "AnasaziEigensolverDecl.hpp" + +namespace Anasazi { + + //! @name StatusTest Exceptions + //@{ + + /** \brief Exception thrown to signal error in a status test during Anasazi::StatusTest::checkStatus(). + */ + class StatusTestError : public AnasaziError + {public: StatusTestError(const std::string& what_arg) : AnasaziError(what_arg) {}}; + + //@} + + +template +class StatusTest { + + public: + //! @name Constructors/destructors + //@{ + + //! Constructor + StatusTest() {}; + + //! Destructor + virtual ~StatusTest() {}; + //@} + + //! @name Status methods + //@{ + /*! Check status as defined by test. + + \return TestStatus indicating whether the test passed or failed. + */ + virtual TestStatus checkStatus( Eigensolver* solver ) = 0; + + //! Return the result of the most recent checkStatus call, or undefined if it has not been run. + virtual TestStatus getStatus() const = 0; + //@} + + //! @name Reset methods + //@{ + //! Informs the status test that it should reset its internal configuration to the uninitialized state. + /*! This is necessary for the case when the status test is being reused by another solver or for another + eigenvalue problem. The status test may have information that pertains to a particular problem or solver + state. The internal information will be reset back to the uninitialized state. The user specified information + that the convergence test uses will remain. + */ + virtual void reset() = 0; + + //! Clears the results of the last status test. + /*! This should be distinguished from the reset() method, as it only clears the cached result from the last + * status test, so that a call to getStatus() will return ::Undefined. This is necessary for the SEQOR and SEQAND + * tests in the StatusTestCombo class, which may short circuit and not evaluate all of the StatusTests contained + * in them. + */ + virtual void clearStatus() = 0; + + //@} + + //! @name Print methods + //@{ + + //! Output formatted description of stopping test to output stream. + virtual std::ostream& print(std::ostream& os, int indent = 0) const = 0; + + //@} + +}; + +} // end of Anasazi namespace + +#endif /* ANASAZI_STATUS_TEST_HPP */ diff --git a/fastlib/trilinos/include/AnasaziStatusTestCombo.hpp b/fastlib/trilinos/include/AnasaziStatusTestCombo.hpp new file mode 100644 index 0000000000..e586ed7f58 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziStatusTestCombo.hpp @@ -0,0 +1,344 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// + +#ifndef ANASAZI_STATUS_TEST_COMBO_HPP +#define ANASAZI_STATUS_TEST_COMBO_HPP + +/*! + \file AnasaziStatusTestCombo.hpp + \brief Status test for forming logical combinations of other status tests. +*/ + + +#include "AnasaziTypes.hpp" +#include "AnasaziStatusTest.hpp" +#include "Teuchos_Array.hpp" + + /*! + \class Anasazi::StatusTestCombo + \brief Status test for forming logical combinations of other status tests. + + Test types include OR, AND, SEQOR and SEQAND. The OR and AND tests + evaluate all of the tests, in the order they were passed to the + StatusTestCombo. The SEQOR and SEQAND run only the tests necessary to + determine the final outcome, short-circuiting on the first test that + conclusively decides the outcome. More formally, SEQAND runs the tests in + the order they were given to the StatusTestCombo class and stops after the + first test that evaluates ::Failed. SEQOR run the tests in the order they + were given to the StatusTestCombo class and stops after the first test that + evaluates ::Passed. + */ + +namespace Anasazi { + + +template +class StatusTestCombo : public StatusTest { + + private: + typedef Teuchos::Array< Teuchos::RCP< StatusTest > > STPArray; + + public: + + //! \brief Enumerated type to list the types of StatusTestCombo combo types. + enum ComboType + { + OR, /*!< Logical OR which evaluates all tests */ + AND, /*!< Logical AND which evaluates all tests */ + SEQOR, /*!< Short-circuited logical OR */ + SEQAND /*!< Short-circuited logical AND */ + }; + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + + typedef Teuchos::Array< Teuchos::RCP< StatusTest > > t_arr; + typedef std::vector< Teuchos::RCP< StatusTest > > st_vector; + typedef typename st_vector::iterator iterator; + typedef typename st_vector::const_iterator const_iterator; + +#endif // DOXYGEN_SHOULD_SKIP_THIS + + //! @name Constructors/destructors + //@{ + + //! Constructor + //! \brief Default constructor has no tests and initializes to ComboType OR. + StatusTestCombo() : state_(Undefined) {} + + //! Constructor + //! \brief Constructor specifying the ComboType and the tests. + StatusTestCombo(ComboType type, Teuchos::Array< Teuchos::RCP< StatusTest > > tests) : + state_(Undefined), + type_(type) + { + setTests(tests); + }; + + //! Destructor + virtual ~StatusTestCombo() {}; + //@} + + //! @name Status methods + //@{ + /*! Check status as defined by test. + + \return TestStatus indicating whether the test passed or failed. + */ + TestStatus checkStatus( Eigensolver* solver ); + + //! Return the result of the most recent checkStatus call. + TestStatus getStatus() const { + return state_; + } + //@} + + //! @name Accessor methods + //@{ + + /*! \brief Set the maximum number of iterations. + * This also resets the test status to ::Undefined. + */ + void setComboType(ComboType type) { + type_ = type; + state_ = Undefined; + } + + //! Get the maximum number of iterations. + ComboType getComboType() const {return type_;} + + /*! \brief Set the tests + * This also resets the test status to ::Undefined. + */ + void setTests(Teuchos::Array > > tests) { + tests_ = tests; + state_ = Undefined; + } + + //! Get the tests + Teuchos::Array > > getTests() const {return tests_;} + + /*! \brief Add a test to the combination. + * + * This also resets the test status to ::Undefined. + */ + void addTest(Teuchos::RCP > test) { + tests_.push_back(test); + state_ = Undefined; + } + + /*! \brief Removes a test from the combination, if it exists in the tester. + * + * This also resets the test status to ::Undefined, if a test was removed. + */ + void removeTest(const Teuchos::RCP > &test); + + //@} + + //! @name Reset methods + //@{ + //! \brief Informs the status test that it should reset its internal configuration to the uninitialized state. + /*! The StatusTestCombo class has no internal state, but children classes might, so this method will call + reset() on all child status tests. It also resets the test status to ::Undefined. + */ + void reset(); + + //! \brief Clears the results of the last status test. + /*! This should be distinguished from the reset() method, as it only clears the cached result from the last + * status test, so that a call to getStatus() will return ::Undefined. This is necessary for the SEQOR and SEQAND + * tests in the StatusTestCombo class, which may short circuit and not evaluate all of the StatusTests contained + * in them. + */ + void clearStatus(); + + //@} + + //! @name Print methods + //@{ + + //! Output formatted description of stopping test to output stream. + std::ostream& print(std::ostream& os, int indent = 0) const; + + //@} + private: + + TestStatus evalOR(Eigensolver* solver); + TestStatus evalAND(Eigensolver* solver); + TestStatus evalSEQOR(Eigensolver* solver); + TestStatus evalSEQAND(Eigensolver* solver); + + TestStatus state_; + ComboType type_; + STPArray tests_; + +}; + + +template +void StatusTestCombo::removeTest(const Teuchos::RCP > &test) +{ + typename STPArray::iterator iter1; + iter1 = find(tests_.begin(),tests_.end(),test); + if (iter1 != tests_.end()) { + tests_.erase(iter1); + state_ = Undefined; + } +} + + +template +TestStatus StatusTestCombo::checkStatus( Eigensolver* solver ) { + clearStatus(); + switch (type_) { + case OR: + state_ = evalOR(solver); + break; + case AND: + state_ = evalAND(solver); + break; + case SEQOR: + state_ = evalSEQOR(solver); + break; + case SEQAND: + state_ = evalSEQAND(solver); + break; + } + return state_; +} + + +template +void StatusTestCombo::reset() { + state_ = Undefined; + for (iterator i=tests_.begin(); i != tests_.end(); i++) { + (*i)->reset(); + } +} + +template +void StatusTestCombo::clearStatus() { + state_ = Undefined; + for (iterator i=tests_.begin(); i != tests_.end(); i++) { + (*i)->clearStatus(); + } +} + +template +std::ostream& StatusTestCombo::print(std::ostream& os, int indent) const { + std::string ind(indent,' '); + os << ind << "- StatusTestCombo: "; + switch (state_) { + case Passed: + os << "Passed" << std::endl; + break; + case Failed: + os << "Failed" << std::endl; + break; + case Undefined: + os << "Undefined" << std::endl; + break; + } + // print children, with extra indention + for (const_iterator i=tests_.begin(); i != tests_.end(); i++) { + (*i)->print(os,indent+2); + } + return os; +} + +template +TestStatus StatusTestCombo::evalOR( Eigensolver* solver ) { + state_ = Failed; + for (iterator i=tests_.begin(); i != tests_.end(); i++) { + TestStatus r = (*i)->checkStatus(solver); + if (r == Passed) { + state_ = Passed; + } + else { + TEST_FOR_EXCEPTION(r != Failed,StatusTestError, + "Anasazi::StatusTestCombo::evalOR(): child test gave invalid return"); + } + } + return state_; +} + +template +TestStatus StatusTestCombo::evalSEQOR( Eigensolver* solver ) { + state_ = Failed; + for (iterator i=tests_.begin(); i != tests_.end(); i++) { + TestStatus r = (*i)->checkStatus(solver); + if (r == Passed) { + state_ = Passed; + break; + } + else { + TEST_FOR_EXCEPTION(r != Failed,StatusTestError, + "Anasazi::StatusTestCombo::evalSEQOR(): child test gave invalid return"); + } + } + return state_; +} + +template +TestStatus StatusTestCombo::evalAND( Eigensolver* solver ) { + state_ = Passed; + for (iterator i=tests_.begin(); i != tests_.end(); i++) { + TestStatus r = (*i)->checkStatus(solver); + if (r == Failed) { + state_ = Failed; + } + else { + TEST_FOR_EXCEPTION(r != Passed,StatusTestError, + "Anasazi::StatusTestCombo::evalAND(): child test gave invalid return"); + } + } + return state_; +} + +template +TestStatus StatusTestCombo::evalSEQAND( Eigensolver* solver ) { + state_ = Passed; + for (iterator i=tests_.begin(); i != tests_.end(); i++) { + TestStatus r = (*i)->checkStatus(solver); + if (r == Failed) { + state_ = Failed; + break; + } + else { + TEST_FOR_EXCEPTION(r != Passed,StatusTestError, + "Anasazi::StatusTestCombo::evalAND(): child test gave invalid return"); + } + } + return state_; +} + + + +} // end of Anasazi namespace + +#endif /* ANASAZI_STATUS_TEST_COMBO_HPP */ diff --git a/fastlib/trilinos/include/AnasaziStatusTestDecl.hpp b/fastlib/trilinos/include/AnasaziStatusTestDecl.hpp new file mode 100644 index 0000000000..1e6bf3b94e --- /dev/null +++ b/fastlib/trilinos/include/AnasaziStatusTestDecl.hpp @@ -0,0 +1,56 @@ +// @HEADER +// *********************************************************************** +// +// Belos: Block Linear Solvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// + +#ifndef ANASAZI_STATUS_TEST_DECL_HPP +#define ANASAZI_STATUS_TEST_DECL_HPP + +/*! + \file AnasaziStatusTestDecl.hpp + \brief Forward declaration of pure virtual base class Anasazi::StatusTest. +*/ + +#include "AnasaziConfigDefs.hpp" +#include "AnasaziTypes.hpp" + +namespace Anasazi { + + /*! + \class StatusTest + \brief A pure virtual class for defining the status tests for the ::Anasazi iterative solvers + + StatusTest is an interface that can be implemented to create convergence tests for + all Anasazi solvers. Almost any kind of test can be expressed using this mechanism, + including composite tests (see StatusTestCombo). + */ + template + class StatusTest; +} + + +#endif diff --git a/fastlib/trilinos/include/AnasaziStatusTestMaxIters.hpp b/fastlib/trilinos/include/AnasaziStatusTestMaxIters.hpp new file mode 100644 index 0000000000..da57585ff3 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziStatusTestMaxIters.hpp @@ -0,0 +1,185 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// + +#ifndef ANASAZI_STATUS_TEST_MAXITER_HPP +#define ANASAZI_STATUS_TEST_MAXITER_HPP + +/*! + \file AnasaziStatusTestMaxIters.hpp + \brief Status test for testing the number of iterations. +*/ + + +#include "AnasaziStatusTest.hpp" + + + /*! + \class Anasazi::StatusTestMaxIters + \brief A status test for testing the number of iterations. + + Anasazi::StatusTestMaxIters will test true when an eigensolver has reached some number + of iterations. Specifically, +
    +                     { Passed,  if solver->getNumIters() >= maxIter
    +    status(solver) = {
    +                     { Failed,  if solver->getNumIters()  < maxIter
    +    
    + where maxIter is the parameter given to the status tester. + + This status test also supports negation, so that it negates the need for a + StatusTestMinIters status tester. In this way, all tests on the range of iterations + can be constructed through the appropriate use of StatusTestMaxIters and StatusTestCombo. + */ + +namespace Anasazi { + + +template +class StatusTestMaxIters : public StatusTest { + + public: + //! @name Constructors/destructors + //@{ + + //! Constructor + StatusTestMaxIters(int maxIter, bool negate = false) : state_(Undefined), negate_(negate) { + setMaxIters(maxIter); + }; + + //! Destructor + virtual ~StatusTestMaxIters() {}; + //@} + + //! @name Status methods + //@{ + + /*! \brief Check status as defined by test. + \return TestStatus indicating whether the test passed or failed. + */ + TestStatus checkStatus( Eigensolver* solver ) { + state_ = (solver->getNumIters() >= maxIters_) ? Passed : Failed; + if (negate_) { + if (state_ == Passed) state_ = Failed; + else state_ = Passed; + } + return state_; + } + + //! \brief Return the result of the most recent checkStatus call. + TestStatus getStatus() const { + return state_; + } + //@} + + //! @name Accessor methods + //@{ + + /*! \brief Set the maximum number of iterations. + * \note This also resets the test status to ::Undefined. + */ + void setMaxIters(int maxIters) { + state_ = Undefined; + maxIters_ = maxIters; + } + + //! \brief Get the maximum number of iterations. + int getMaxIters() {return maxIters_;} + + /*! \brief Set the negation policy for the status test. + * \note This also reset the test status to ::Undefined. + */ + void setNegate(bool negate) { + state_ = Undefined; + negate_ = negate; + } + + //! \brief Get the negation policy for the status test. + bool getNegate() const { + return negate_; + } + + //@} + + //! @name Reset methods + //@{ + //! Informs the status test that it should reset its internal configuration to the uninitialized state. + /*! The StatusTestMaxIters class has no internal state, so this call is equivalent to calling clearStatus(). + eigenvalue problem. The status test may have information that pertains to a particular problem or solver + state. The internal information will be reset back to the uninitialized state. The user specified information + that the convergence test uses will remain. + */ + void reset() { + state_ = Undefined; + } + + //! \brief Clears the results of the last status test. + /*! This should be distinguished from the reset() method, as it only clears the cached result from the last + * status test, so that a call to getStatus() will return ::Undefined. This is necessary for the SEQOR and SEQAND + * tests in the StatusTestCombo class, which may short circuit and not evaluate all of the StatusTests contained + * in them. + */ + void clearStatus() { + state_ = Undefined; + } + + //@} + + //! @name Print methods + //@{ + + //! Output formatted description of stopping test to output stream. + std::ostream& print(std::ostream& os, int indent = 0) const { + std::string ind(indent,' '); + os << ind << "- StatusTestMaxIters: "; + switch (state_) { + case Passed: + os << "Passed" << std::endl; + break; + case Failed: + os << "Failed" << std::endl; + break; + case Undefined: + os << "Undefined" << std::endl; + break; + } + os << ind << " MaxIters: " << maxIters_ << std::endl; + return os; + } + + //@} + private: + int maxIters_; + TestStatus state_; + bool negate_; + +}; + +} // end of Anasazi namespace + +#endif /* ANASAZI_STATUS_TEST_MAXITER_HPP */ diff --git a/fastlib/trilinos/include/AnasaziStatusTestOrderedResNorm.hpp b/fastlib/trilinos/include/AnasaziStatusTestOrderedResNorm.hpp new file mode 100644 index 0000000000..78ddbc8225 --- /dev/null +++ b/fastlib/trilinos/include/AnasaziStatusTestOrderedResNorm.hpp @@ -0,0 +1,377 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// + +#ifndef ANASAZI_STATUS_TEST_ORDEREDRESNORM_HPP +#define ANASAZI_STATUS_TEST_ORDEREDRESNORM_HPP + +/*! + \file AnasaziStatusTestOrderedResNorm.hpp + \brief A status test for testing the norm of the eigenvectors residuals along with a + set of auxiliary eigenvalues. +*/ + + +#include "AnasaziStatusTest.hpp" +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_LAPACK.hpp" + + /*! + \class Anasazi::StatusTestOrderedResNorm + + \brief A status test for testing the norm of the eigenvectors residuals + along with a set of auxiliary eigenvalues. + + The test evaluates to ::Passed when then the most significant of the + eigenvalues all have a residual below a certain threshhold. The purpose of + the test is to not only test convergence for some number of eigenvalues, + but to test convergence for the correct ones. + + In addition to specifying the tolerance, the user may specify: +
      +
    • the norm to be used: 2-norm or OrthoManager::norm() or getRitzRes2Norms() +
    • the scale: absolute or relative to magnitude of Ritz value +
    • the quorum: the number of vectors required for the test to + evaluate as ::Passed. +
    + + Finally, the user must specify the Anasazi::SortManager used for deciding + significance. + */ + +namespace Anasazi { + + +template +class StatusTestOrderedResNorm : public StatusTest { + + private: + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + typedef Teuchos::ScalarTraits MT; + + public: + + //! @name Enums + //@{ + + /*! \enum ResType + \brief Enumerated type used to specify which residual norm used by this status test. + */ + enum ResType { + RES_ORTH, + RES_2NORM, + RITZRES_2NORM + }; + + //@} + + //! @name Constructors/destructors + //@{ + + //! Constructor + StatusTestOrderedResNorm(Teuchos::RCP > sorter, typename Teuchos::ScalarTraits::magnitudeType tol, int quorum = -1, ResType whichNorm = RES_ORTH, bool scaled = true); + + //! Destructor + virtual ~StatusTestOrderedResNorm() {}; + //@} + + //! @name Status methods + //@{ + /*! Check status as defined by test. + \return TestStatus indicating whether the test passed or failed. + */ + TestStatus checkStatus( Eigensolver* solver ); + + //! Return the result of the most recent checkStatus call. + TestStatus getStatus() const { return state_; } + //@} + + //! @name Accessor methods + //@{ + + /*! \brief Set tolerance. + * This also resets the test status to ::Undefined. + */ + void setTolerance(typename Teuchos::ScalarTraits::magnitudeType tol) { + state_ = Undefined; + tol_ = tol; + } + + //! Get tolerance. + typename Teuchos::ScalarTraits::magnitudeType getTolerance() {return tol_;} + + /*! \brief Set the residual norm to be used by the status test. + * + * This also resets the test status to ::Undefined. + */ + void setWhichNorm(ResType whichNorm) { + state_ = Undefined; + whichNorm_ = whichNorm; + } + + //! Return the residual norm used by the status test. + ResType getWhichNorm() {return whichNorm_;} + + /*! \brief Instruct test to scale norms by eigenvalue estimates (relative scale). + * This also resets the test status to ::Undefined. + */ + void setScale(bool relscale) { + state_ = Undefined; + scaled_ = relscale; + } + + //! Returns true if the test scales the norms by the eigenvalue estimates (relative scale). + bool getScale() {return scaled_;} + + //! Get the indices for the vectors that passed the test. + std::vector whichVecs() { + return ind_; + } + + //! Get the number of vectors that passed the test. + int howMany() { + return ind_.size(); + } + + //@} + + //! @name Reset methods + //@{ + //! Informs the status test that it should reset its internal configuration to the uninitialized state. + /*! This is necessary for the case when the status test is being reused by another solver or for another + eigenvalue problem. The status test may have information that pertains to a particular problem or solver + state. The internal information will be reset back to the uninitialized state. The user specified information + that the convergence test uses will remain. + */ + void reset() { + state_ = Undefined; + } + + //! Clears the results of the last status test. + /*! This should be distinguished from the reset() method, as it only clears the cached result from the last + * status test, so that a call to getStatus() will return ::Undefined. This is necessary for the SEQOR and SEQAND + * tests in the StatusTestCombo class, which may short circuit and not evaluate all of the StatusTests contained + * in them. + */ + void clearStatus() { + state_ = Undefined; + } + + /*! \brief Set the auxiliary eigenvalues. + * + * This routine sets only the real part of the auxiliary eigenvalues; the imaginary part is set to zero. This routine also resets the state to ::Undefined. + */ + void setAuxVals(const std::vector::magnitudeType> &vals) { + rvals_ = vals; + ivals_.resize(rvals_.size(),MT::zero()); + state_ = Undefined; + } + + /*! \brief Set the auxiliary eigenvalues. + * + * This routine sets both the real and imaginary parts of the auxiliary eigenvalues. This routine also resets the state to ::Undefined. + */ + void setAuxVals(const std::vector::magnitudeType> &rvals, const std::vector::magnitudeType> &ivals) { + rvals_ = rvals; + ivals_ = ivals; + state_ = Undefined; + } + + //@} + + //! @name Print methods + //@{ + + //! Output formatted description of stopping test to output stream. + std::ostream& print(std::ostream& os, int indent = 0) const; + + //@} + private: + TestStatus state_; + MagnitudeType tol_; + std::vector ind_; + int quorum_; + bool scaled_; + ResType whichNorm_; + std::vector rvals_, ivals_; + Teuchos::RCP > sorter_; +}; + + +template +StatusTestOrderedResNorm::StatusTestOrderedResNorm(Teuchos::RCP > sorter, typename Teuchos::ScalarTraits::magnitudeType tol, int quorum, ResType whichNorm, bool scaled) + : state_(Undefined), quorum_(quorum), scaled_(scaled), whichNorm_(whichNorm), sorter_(sorter) +{ + TEST_FOR_EXCEPTION(sorter_ == Teuchos::null, StatusTestError, "StatusTestOrderedResNorm::constructor() was passed null pointer for SortManager."); + setTolerance(tol); +} + +template +TestStatus StatusTestOrderedResNorm::checkStatus( Eigensolver* solver ) { + + + // get the eigenvector/ritz residuals norms (using the appropriate norm) + // get the eigenvalues/ritzvalues as well + std::vector res; + std::vector > vals = solver->getRitzValues(); + switch (whichNorm_) { + case RES_2NORM: + res = solver->getRes2Norms(); + vals.resize(res.size()); + break; + case RES_ORTH: + res = solver->getResNorms(); + vals.resize(res.size()); + break; + case RITZRES_2NORM: + res = solver->getRitzRes2Norms(); + break; + } + + int numaux = rvals_.size(); + int bs = res.size(); + int num = bs + numaux; + + if (num == 0) { + ind_.resize(0); + return Failed; + } + + // extract the real and imaginary parts from the + std::vector allrvals(bs), allivals(bs); + for (int i=0; i lapack; + if (scaled_) { + for (unsigned int i=0; i perm(num,-1); + sorter_->sort(solver,num,allrvals,allivals,&perm); + + // apply the sorting to the residuals and original indices + std::vector oldres = res; + for (int i=0; i num ? num : need; + for (int i=0; i= need) ? Passed : Failed; + return state_; +} + + +template +std::ostream& StatusTestOrderedResNorm::print(std::ostream& os, int indent) const { + std::string ind(indent,' '); + os << ind << "- StatusTestOrderedResNorm: "; + switch (state_) { + case Passed: + os << "Passed" << std::endl; + break; + case Failed: + os << "Failed" << std::endl; + break; + case Undefined: + os << "Undefined" << std::endl; + break; + } + os << ind << " (Tolerance,WhichNorm,Scaled,Quorum): " + << "(" << tol_; + switch (whichNorm_) { + case RES_ORTH: + os << ",RES_ORTH"; + break; + case RES_2NORM: + os << ",RES_2NORM"; + break; + case RITZRES_2NORM: + os << ",RITZRES_2NORM"; + break; + } + os << "," << (scaled_ ? "true" : "false") + << "," << quorum_ + << ")" << std::endl; + os << ind << " Auxiliary values: "; + if (rvals_.size() > 0) { + for (unsigned int i=0; i 0) { + for (unsigned int i=0; i +class StatusTestOutput : public StatusTest { + + public: + //! @name Constructors/destructors + //@{ + + /*! \brief Constructor + * + * The StatusTestOutput requires an OutputManager for printing the underlying StatusTest on + * calls to checkStatus(), as well as an underlying StatusTest. + * + * The last two parameters, described below, in addition to the verbosity level of the OutputManager, control when printing is + * called. When both the \c mod criterion and the \c printStates criterion are satisfied, the status test will be printed to the + * OutputManager with ::MsgType of ::StatusTestDetails. + * + * @param[in] mod A positive number describes how often the output should be printed. On every call to checkStatus(), an internal counter + * is incremented. Printing may only occur when this counter is congruent to zero modulo \c mod. Default: 1 (attempt to print on every call to checkStatus()) + * @param[in] printStates A combination of ::TestStatus values for which the output may be printed. Default: ::Passed (attempt to print whenever checkStatus() will return ::Passed) + * + */ + StatusTestOutput(const Teuchos::RCP > &printer, + Teuchos::RCP > test, + int mod = 1, + int printStates = Passed) + : printer_(printer), test_(test), state_(Undefined), stateTest_(printStates), modTest_(mod), numCalls_(0) {} + + //! Destructor + virtual ~StatusTestOutput() {}; + //@} + + //! @name Status methods + //@{ + /*! Check and return status of underlying StatusTest. + + This method calls checkStatus() on the StatusTest object passed in the constructor. If appropriate, the + method will follow this call with a call to print() on the underlying object, using the OutputManager passed via the constructor + with verbosity level ::StatusTestDetails. + + The internal counter will be incremented during this call, but only after + performing the tests to decide whether or not to print the underlying + StatusTest. This way, the very first call to checkStatus() following + initialization or reset() will enable the underlying StatusTest to be + printed, regardless of the mod parameter, as the current number of calls + will be zero. + + If the specified Teuchos::RCP for the child class is Teuchos::null, then calling checkStatus() will result in a StatusTestError exception being thrown. + + \return ::TestStatus indicating whether the underlying test passed or failed. + */ + TestStatus checkStatus( Eigensolver* solver ) { + TEST_FOR_EXCEPTION(test_ == Teuchos::null,StatusTestError,"StatusTestOutput::checkStatus(): child pointer is null."); + state_ = test_->checkStatus(solver); + + if (numCalls_++ % modTest_ == 0) { + if ( (state_ & stateTest_) == state_) { + if ( printer_->isVerbosity(StatusTestDetails) ) { + print( printer_->stream(StatusTestDetails) ); + } + else if ( printer_->isVerbosity(Debug) ) { + print( printer_->stream(Debug) ); + } + } + } + + return state_; + } + + //! Return the result of the most recent checkStatus call, or undefined if it has not been run. + TestStatus getStatus() const { + return state_; + } + //@} + + + //! @name Accessor methods + //@{ + + /*! \brief Set child test. + * + * \note This also resets the test status to ::Undefined. + */ + void setChild(Teuchos::RCP > test) { + test_ = test; + state_ = Undefined; + } + + //! \brief Get child test. + Teuchos::RCP > getChild() const { + return test_; + } + + //@} + + + //! @name Reset methods + //@{ + /*! \brief Informs the status test that it should reset its internal configuration to the uninitialized state. + * + * This resets the cached state to an ::Undefined state and calls reset() on the underlying test. It also + * resets the counter for the number of calls to checkStatus(). + */ + void reset() { + state_ = Undefined; + test_->reset(); + numCalls_ = 0; + } + + //! Clears the results of the last status test. + //! This resets the cached state to an ::Undefined state and calls clearStatus() on the underlying test. + void clearStatus() { + state_ = Undefined; + test_->clearStatus(); + } + + //@} + + //! @name Print methods + //@{ + + //! Output formatted description of stopping test to output stream. + std::ostream& print(std::ostream& os, int indent = 0) const { + std::string ind(indent,' '); + os << ind << "- StatusTestOutput: "; + switch (state_) { + case Passed: + os << "Passed" << std::endl; + break; + case Failed: + os << "Failed" << std::endl; + break; + case Undefined: + os << "Undefined" << std::endl; + break; + } + os << ind << " (Num calls,Mod test,State test): " << "(" << numCalls_ << ", " << modTest_ << ","; + if (stateTest_ == 0) { + os << " none )" << std::endl; + } + else { + if ( (stateTest_ & Passed) == Passed ) os << " Passed"; + if ( (stateTest_ & Failed) == Failed ) os << " Failed"; + if ( (stateTest_ & Undefined) == Undefined ) os << " Undefined"; + os << " )" << std::endl; + } + // print child, with extra indention + test_->print(os,indent+3); + return os; + } + + //@} + + private: + Teuchos::RCP > printer_; + Teuchos::RCP > test_; + TestStatus state_; + int stateTest_; + int modTest_; + int numCalls_; +}; + +} // end of Anasazi namespace + +#endif /* ANASAZI_STATUS_TEST_OUTPUT_HPP */ diff --git a/fastlib/trilinos/include/AnasaziStatusTestResNorm.hpp b/fastlib/trilinos/include/AnasaziStatusTestResNorm.hpp new file mode 100644 index 0000000000..65aed2ad0c --- /dev/null +++ b/fastlib/trilinos/include/AnasaziStatusTestResNorm.hpp @@ -0,0 +1,317 @@ +// @HEADER +// *********************************************************************** +// +// Anasazi: Block Eigensolvers Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +// + +#ifndef ANASAZI_STATUS_TEST_RESNORM_HPP +#define ANASAZI_STATUS_TEST_RESNORM_HPP + +/*! + \file AnasaziStatusTestResNorm.hpp + \brief A status test for testing the norm of the eigenvectors residuals. +*/ + + +#include "AnasaziStatusTest.hpp" +#include "Teuchos_ScalarTraits.hpp" + + /*! + \class Anasazi::StatusTestResNorm + \brief A status test for testing the norm of the eigenvectors residuals. + + Anasazi::StatusTestResNorm was designed to be used as a test for + convergence. The tester compares the norms of the residual vectors against + a user specified tolerance. + + In addition to specifying the tolerance, the user may specify: +
      +
    • the norm to be used: 2-norm or OrthoManager::norm() or getRitzRes2Norms() +
    • the scale: absolute or relative to magnitude of Ritz value +
    • the quorum: the number of vectors required for the test to + evaluate as ::Passed. +
    + */ + +namespace Anasazi { + + +template +class StatusTestResNorm : public StatusTest { + + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + + public: + + //! @name Enums + //@{ + + /*! \enum ResType + \brief Enumerated type used to specify which residual norm used by this status test. + */ + enum ResType { + RES_ORTH, + RES_2NORM, + RITZRES_2NORM + }; + + //@} + + //! @name Constructors/destructors + //@{ + + //! Constructor + StatusTestResNorm(typename Teuchos::ScalarTraits::magnitudeType tol, int quorum = -1, ResType whichNorm = RES_ORTH, bool scaled = true); + + //! Destructor + virtual ~StatusTestResNorm() {}; + //@} + + //! @name Status methods + //@{ + /*! Check status as defined by test. + \return TestStatus indicating whether the test passed or failed. + */ + TestStatus checkStatus( Eigensolver* solver ); + + //! Return the result of the most recent checkStatus call. + TestStatus getStatus() const { return state_; } + //@} + + //! @name Accessor methods + //@{ + + /*! \brief Set quorum. + * + * Setting quorum to -1 signifies that all residuals from the solver must meet the tolerance. + * This also resets the test status to ::Undefined. + */ + void setQuorum(int quorum) { + state_ = Undefined; + quorum_ = quorum; + } + + /*! \brief Get quorum. + */ + int getQuorum() { + return quorum_; + } + + /*! \brief Set tolerance. + * This also resets the test status to ::Undefined. + */ + void setTolerance(typename Teuchos::ScalarTraits::magnitudeType tol) { + state_ = Undefined; + tol_ = tol; + } + + //! Get tolerance. + typename Teuchos::ScalarTraits::magnitudeType getTolerance() {return tol_;} + + /*! \brief Set the residual norm to be used by the status test. + * + * This also resets the test status to ::Undefined. + */ + void setWhichNorm(ResType whichNorm) { + state_ = Undefined; + whichNorm_ = whichNorm; + } + + //! Return the residual norm used by the status test. + ResType getWhichNorm() {return whichNorm_;} + + /*! \brief Instruct test to scale norms by eigenvalue estimates (relative scale). + * This also resets the test status to ::Undefined. + */ + void setScale(bool relscale) { + state_ = Undefined; + scaled_ = relscale; + } + + //! Returns true if the test scales the norms by the eigenvalue estimates (relative scale). + bool getScale() {return scaled_;} + + //! Get the indices for the vectors that passed the test. + std::vector whichVecs() { + return ind_; + } + + //! Get the number of vectors that passed the test. + int howMany() { + return ind_.size(); + } + + //@} + + //! @name Reset methods + //@{ + //! Informs the status test that it should reset its internal configuration to the uninitialized state. + /*! This is necessary for the case when the status test is being reused by another solver or for another + eigenvalue problem. The status test may have information that pertains to a particular problem or solver + state. The internal information will be reset back to the uninitialized state. The user specified information + that the convergence test uses will remain. + */ + void reset() { + state_ = Undefined; + } + + //! Clears the results of the last status test. + /*! This should be distinguished from the reset() method, as it only clears the cached result from the last + * status test, so that a call to getStatus() will return ::Undefined. This is necessary for the SEQOR and SEQAND + * tests in the StatusTestCombo class, which may short circuit and not evaluate all of the StatusTests contained + * in them. + */ + void clearStatus() { + state_ = Undefined; + } + + //@} + + //! @name Print methods + //@{ + + //! Output formatted description of stopping test to output stream. + std::ostream& print(std::ostream& os, int indent = 0) const; + + //@} + private: + TestStatus state_; + MagnitudeType tol_; + std::vector ind_; + int quorum_; + bool scaled_; + ResType whichNorm_; +}; + + +template +StatusTestResNorm::StatusTestResNorm(typename Teuchos::ScalarTraits::magnitudeType tol, int quorum, ResType whichNorm, bool scaled) + : state_(Undefined), tol_(tol), quorum_(quorum), scaled_(scaled), whichNorm_(whichNorm) {} + +template +TestStatus StatusTestResNorm::checkStatus( Eigensolver* solver ) { + typedef Teuchos::ScalarTraits MT; + + std::vector res; + + // get the eigenvector/ritz residuals norms (using the appropriate norm) + // get the eigenvalues/ritzvalues and ritz index as well + std::vector > vals = solver->getRitzValues(); + switch (whichNorm_) { + case RES_2NORM: + res = solver->getRes2Norms(); + // we want only the ritz values corresponding to our eigenvector residuals + vals.resize(res.size()); + break; + case RES_ORTH: + res = solver->getResNorms(); + // we want only the ritz values corresponding to our eigenvector residuals + vals.resize(res.size()); + break; + case RITZRES_2NORM: + res = solver->getRitzRes2Norms(); + break; + } + + // if appropriate, scale the norms by the magnitude of the eigenvalue estimate + if (scaled_) { + Teuchos::LAPACK lapack; + + for (unsigned int i=0; i= need) ? Passed : Failed; + return state_; +} + + +template +std::ostream& StatusTestResNorm::print(std::ostream& os, int indent) const { + std::string ind(indent,' '); + os << ind << "- StatusTestResNorm: "; + switch (state_) { + case Passed: + os << "Passed" << std::endl; + break; + case Failed: + os << "Failed" << std::endl; + break; + case Undefined: + os << "Undefined" << std::endl; + break; + } + os << ind << " (Tolerance,WhichNorm,Scaled,Quorum): " + << "(" << tol_; + switch (whichNorm_) { + case RES_ORTH: + os << ",RES_ORTH"; + break; + case RES_2NORM: + os << ",RES_2NORM"; + break; + case RITZRES_2NORM: + os << ",RITZRES_2NORM"; + break; + } + os << "," << (scaled_ ? "true" : "false") + << "," << quorum_ + << ")" << std::endl; + + if (state_ != Undefined) { + os << ind << " Which vectors: "; + if (ind_.size() > 0) { + for (unsigned int i=0; i + struct Value { + //! The real component of the eigenvalue. + typename Teuchos::ScalarTraits::magnitudeType realpart; + //! The imaginary component of the eigenvalue. + typename Teuchos::ScalarTraits::magnitudeType imagpart; + void set(const typename Teuchos::ScalarTraits::magnitudeType &rp, const typename Teuchos::ScalarTraits::magnitudeType &ip){ + realpart=rp;imagpart=ip; + } + Value &operator=(const Value &rhs) { + realpart=rhs.realpart;imagpart=rhs.imagpart; + return *this; + } + }; + + //! Struct for storing an eigenproblem solution. + template + struct Eigensolution { + //! The computed eigenvectors + Teuchos::RCP Evecs; + //! An orthonormal basis for the computed eigenspace + Teuchos::RCP Espace; + //! The computed eigenvalues + std::vector > Evals; + /*! \brief An index into Evecs to allow compressed storage of eigenvectors for real, non-Hermitian problems. + * + * index has length numVecs, where each entry is 0, +1, or -1. These have the following interpretation: + * - index[i] == 0: signifies that the corresponding eigenvector is stored as the i column of Evecs. This will usually be the + * case when ScalarType is complex, an eigenproblem is Hermitian, or a real, non-Hermitian eigenproblem has a real eigenvector. + * - index[i] == +1: signifies that the corresponding eigenvector is stored in two vectors: the real part in the i column of Evecs and the positive imaginary part in the i+1 column of Evecs. + * - index[i] == -1: signifies that the corresponding eigenvector is stored in two vectors: the real part in the i-1 column of Evecs and the negative imaginary part in the i column of Evecs + */ + std::vector index; + //! The number of computed eigenpairs + int numVecs; + + Eigensolution() : Evecs(),Espace(),Evals(0),index(0),numVecs(0) {} + }; + + //@} + + //! @name Anasazi Enumerations + //@{ + + /*! \enum ReturnType + \brief Enumerated type used to pass back information from a solver manager. + */ + enum ReturnType + { + Converged, /*!< The solver manager computed the requested eigenvalues. */ + Unconverged /*!< This solver manager did not compute all of the requested eigenvalues. */ + }; + + + /*! \enum ConjType + * + * \brief Enumerated types used to specify conjugation arguments. + */ + enum ConjType + { + NO_CONJ, /*!< Not conjugated */ + CONJ /*!< Conjugated */ + }; + + + /*! \enum TestStatus + \brief Enumerated type used to pass back information from a StatusTest + */ + enum TestStatus + { + Passed = 0x1, /*!< The solver passed the test */ + Failed = 0x2, /*!< The solver failed the test */ + Undefined = 0x4 /*!< The test has not been evaluated on the solver */ + }; + + + /*! \enum MsgType + \brief Enumerated list of available message types recognized by the eigensolvers. + */ + enum MsgType + { + Errors = 0, /*!< Errors [ always printed ] */ + Warnings = 0x1, /*!< Internal warnings */ + IterationDetails = 0x2, /*!< Approximate eigenvalues, errors */ + OrthoDetails = 0x4, /*!< Orthogonalization/orthonormalization details */ + FinalSummary = 0x8, /*!< Final computational summary */ + TimingDetails = 0x10, /*!< Timing details */ + StatusTestDetails = 0x20, /*!< Status test details */ + Debug = 0x40 /*!< Debugging information */ + }; + + //@} + +} // end of namespace Anasazi +#endif +// end of file AnasaziTypes.hpp diff --git a/fastlib/trilinos/include/Anasazi_config.h b/fastlib/trilinos/include/Anasazi_config.h new file mode 100644 index 0000000000..15125124f1 --- /dev/null +++ b/fastlib/trilinos/include/Anasazi_config.h @@ -0,0 +1,214 @@ +/* src/Anasazi_config.h. Generated from Anasazi_config.h.in by configure. */ +/* src/Anasazi_config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to dummy `main' function (if any) required to link to the Fortran + libraries. */ +/* #undef F77_DUMMY_MAIN */ + +/* Define to a macro mangling the given C identifier (in lower and upper + case), which must not contain underscores, for linking with Fortran. */ +#define F77_FUNC(name,NAME) name ## _ + +/* As F77_FUNC, but for C identifiers containing underscores. */ +#define F77_FUNC_(name,NAME) name ## __ + +/* Define if F77 and FC dummy `main' functions are identical. */ +/* #undef FC_DUMMY_MAIN_EQ_F77 */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ALGORITHM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALGORITHM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ALGO_H */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_AMESOS */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_AZTECOO */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_BELOS */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_EPETRAEXT */ + +/* Define if want to build anasazi-examples */ +#define HAVE_ANASAZI_EXAMPLES + +/* Define if want to build anasazi-experimental */ +/* #undef HAVE_ANASAZI_EXPERIMENTAL */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_IFPACK */ + +/* Define if want to build anasazi-tests */ +#define HAVE_ANASAZI_TESTS + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_THYRA */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_TPETRA */ + +/* Define if want to build with anasazi enabled */ +/* #undef HAVE_ANASAZI_TRIUTILS */ + +/* Define if you have a BLAS library. */ +#define HAVE_BLAS 1 + +/* define if bool is a built-in type */ +#define HAVE_BOOL + +/* Define to 1 if you have the header file. */ +#define HAVE_CMATH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_COMPLEX 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_COMPLEX_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_CSTDIO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CSTDLIB 1 + +/* Define if want to build with epetra enabled */ +/* #undef HAVE_EPETRA_THYRA */ + +/* Define if want to build examples */ +#define HAVE_EXAMPLES + +/* Define if you want to build export makefiles. */ +#define HAVE_EXPORT_MAKEFILES + +/* Define if you are using gnumake - this will shorten your link lines. */ +/* #undef HAVE_GNUMAKE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IOMANIP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IOMANIP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IOSTREAM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IOSTREAM_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_ITERATOR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ITERATOR_H */ + +/* Define if you have LAPACK library. */ +#define HAVE_LAPACK 1 + +/* Define if want to build libcheck */ +#define HAVE_LIBCHECK + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_MATH_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* define if we want to use MPI */ +/* #undef HAVE_MPI */ + +/* define if the compiler supports the mutable keyword */ +#define HAVE_MUTABLE + +/* define if the compiler implements namespaces */ +#define HAVE_NAMESPACES + +/* define if the compiler accepts the new for scoping rules */ +#define HAVE_NEW_FOR_SCOPING + +/* Define to 1 if you have the header file. */ +#define HAVE_NUMERIC 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDEXCEPT 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDEXCEPT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* define if std::sprintf is supported */ +#define HAVE_STD_SPRINTF + +/* define if the compiler supports Standard Template Library */ +#define HAVE_STL + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if want to build tests */ +#define HAVE_TESTS + +/* Define if want to build teuchos-complex */ +#define HAVE_TEUCHOS_COMPLEX + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_VECTOR 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_VECTOR_H */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "hkthorn@sandia.gov" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "anasazi" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "anasazi 2.1" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "anasazi" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "2.1" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif diff --git a/fastlib/trilinos/include/Epetra_BLAS.h b/fastlib/trilinos/include/Epetra_BLAS.h new file mode 100644 index 0000000000..bc8b14d369 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_BLAS.h @@ -0,0 +1,166 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_BLAS_H +#define EPETRA_BLAS_H + +#include "Epetra_Object.h" + +//! Epetra_BLAS: The Epetra BLAS Wrapper Class. +/*! The Epetra_BLAS class is a wrapper that encapsulates the BLAS + (Basic Linear Algebra Subprograms). The BLAS provide portable, high- + performance implementations of kernels such as dense vectoer multiplication, + dot products, dense matrix-vector multiplication and dense matrix-matrix + multiplication. + + The standard BLAS interface is Fortran-specific. Unfortunately, the + interface between C++ and Fortran is not standard across all computer + platforms. The Epetra_BLAS class provides C++ wrappers for the BLAS + kernels in order to insulate the rest of Epetra from the details of C++ to Fortran + translation. + A Epetra_BLAS object is essentially nothing, but allows access to the BLAS wrapper + functions. + + Epetra_BLAS is a serial interface only. This is appropriate since the standard + BLAS are only specified for serial execution (or shared memory parallel). +*/ + + +class Epetra_BLAS { + + public: + //! @name Constructors/Destructor + //@{ + //! Epetra_BLAS Constructor. + /*! Builds an instance of a serial BLAS object. + */ + Epetra_BLAS(void); + + + //! Epetra_BLAS Copy Constructor. + /*! Makes an exact copy of an existing Epetra_BLAS instance. + */ + Epetra_BLAS(const Epetra_BLAS& BLAS); + + //! Epetra_BLAS Destructor. + virtual ~Epetra_BLAS(void); + //@} + + //! @name Level 1 BLAS + //@{ + //! Epetra_BLAS one norm function (SASUM). + float ASUM(const int N, const float * X, const int INCX = 1) const; + //! Epetra_BLAS one norm function (DASUM). + double ASUM(const int N, const double * X, const int INCX = 1) const; + + //! Epetra_BLAS dot product function (SDOT). + float DOT(const int N, const float * X, const float * Y, const int INCX = 1, const int INCY = 1) const; + //! Epetra_BLAS dot product function (DDOT). + double DOT(const int N, const double * X, const double * Y, const int INCX = 1, const int INCY = 1) const; + + //! Epetra_BLAS norm function (SNRM2). + float NRM2(const int N, const float * X, const int INCX = 1) const; + //! Epetra_BLAS norm function (DNRM2). + double NRM2(const int N, const double * X, const int INCX = 1) const; + + //! Epetra_BLAS vector scale function (SSCAL) + void SCAL( const int N, const float ALPHA, float * X, const int INCX = 1) const; + //! Epetra_BLAS vector scale function (DSCAL) + void SCAL( const int N, const double ALPHA, double * X, const int INCX = 1) const; + + //! Epetra_BLAS vector copy function (SCOPY) + void COPY( const int N, const float * X, float * Y, const int INCX = 1, const int INCY = 1) const; + //! Epetra_BLAS vector scale function (DCOPY) + void COPY( const int N, const double * X, double * Y, const int INCX = 1, const int INCY = 1) const; + + //! Epetra_BLAS arg maximum of absolute value function (ISAMAX) + int IAMAX( const int N, const float * X, const int INCX = 1) const; + //! Epetra_BLAS arg maximum of absolute value function (IDAMAX) + int IAMAX( const int N, const double * X, const int INCX = 1) const; + + //! Epetra_BLAS vector update function (SAXPY) + void AXPY( const int N, const float ALPHA, const float * X, float * Y, const int INCX = 1, const int INCY = 1) const; + //! Epetra_BLAS vector update function (DAXPY) + void AXPY( const int N, const double ALPHA, const double * X, double * Y, const int INCX = 1, const int INCY = 1) const; + //@} + + //! @name Level 2 BLAS + //@{ + //! Epetra_BLAS matrix-vector multiply function (SGEMV) + void GEMV(const char TRANS, const int M, const int N, + const float ALPHA, const float * A, const int LDA, const float * X, + const float BETA, float * Y, const int INCX = 1, const int INCY = 1) const; + //! Epetra_BLAS matrix-vector multiply function (DGEMV) + void GEMV(const char TRANS, const int M, const int N, + const double ALPHA, const double * A, const int LDA, const double * X, + const double BETA, double * Y, const int INCX = 1, const int INCY = 1) const; + //@} + + + //! @name Level 3 BLAS + //@{ + //! Epetra_BLAS matrix-matrix multiply function (SGEMM) + void GEMM(const char TRANSA, const char TRANSB, const int M, const int N, const int K, + const float ALPHA, const float * A, const int LDA, const float * B, + const int LDB, const float BETA, float * C, const int LDC) const; + //! Epetra_BLAS matrix-matrix multiply function (DGEMM) + void GEMM(const char TRANSA, const char TRANSB, const int M, const int N, const int K, + const double ALPHA, const double * A, const int LDA, const double * B, + const int LDB, const double BETA, double * C, const int LDC) const; + + //! Epetra_BLAS symmetric matrix-matrix multiply function (SSYMM) + void SYMM(const char SIDE, const char UPLO, const int M, const int N, + const float ALPHA, const float * A, const int LDA, const float * B, + const int LDB, const float BETA, float * C, const int LDC) const; + //! Epetra_BLAS matrix-matrix multiply function (DSYMM) + void SYMM(const char SIDE, const char UPLO, const int M, const int N, + const double ALPHA, const double * A, const int LDA, const double * B, + const int LDB, const double BETA, double * C, const int LDC) const; + + //! Epetra_BLAS triangular matrix-matrix multiply function (STRMM) + void TRMM(const char SIDE, const char UPLO, const char TRANSA, const char DIAG, const int M, const int N, + const float ALPHA, const float * A, const int LDA, float * B, + const int LDB) const; + //! Epetra_BLAS triangular matrix-matrix multiply function (DTRMM) + void TRMM(const char SIDE, const char UPLO, const char TRANSA, const char DIAG, const int M, const int N, + const double ALPHA, const double * A, const int LDA, double * B, + const int LDB) const; + //@} +}; + +// Epetra_BLAS constructor +inline Epetra_BLAS::Epetra_BLAS(void){} +// Epetra_BLAS constructor +inline Epetra_BLAS::Epetra_BLAS(const Epetra_BLAS& BLAS){(void)BLAS;} +// Epetra_BLAS destructor +inline Epetra_BLAS::~Epetra_BLAS(){} + +#endif /* EPETRA_BLAS_H */ diff --git a/fastlib/trilinos/include/Epetra_BLAS_wrappers.h b/fastlib/trilinos/include/Epetra_BLAS_wrappers.h new file mode 100644 index 0000000000..4aaa07a37a --- /dev/null +++ b/fastlib/trilinos/include/Epetra_BLAS_wrappers.h @@ -0,0 +1,266 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_BLAS_WRAPPERS_H +#define EPETRA_BLAS_WRAPPERS_H + +#include "Epetra_ConfigDefs.h" +/* #include */ +/* #include */ + + +/* Define fcd (Fortran Epetra_fcd descriptor) for non-standard situations */ + +#if defined(CRAY_T3X) || defined(INTEL_CXML) || defined(INTEL_MKL) + + +#if defined(CRAY_T3X) + +#include +#define PREFIX +#define Epetra_fcd fcd + +#define DASUM_F77 SASUM +#define DAXPY_F77 SAXPY +#define DCOPY_F77 SCOPY +#define DDOT_F77 SDOT +#define DNRM2_F77 SNRM2 +#define DSCAL_F77 SSCAL +#define IDAMAX_F77 ISAMAX +#define DGEMV_F77 SGEMV +#define DGER_F77 SGER +#define DTRMV_F77 STRMV +#define DGEMM_F77 SGEMM +#define DSYMM_F77 SSYMM +#define DTRMM_F77 STRMM +#define DTRSM_F77 STRSM +#define EPETRA_DCRSMV_F77 EPETRA_DCRSMV +#define EPETRA_DCRSMM_F77 EPETRA_DCRSMM +#define EPETRA_DCRSSV_F77 EPETRA_DCRSSV +#define EPETRA_DCRSSM_F77 EPETRA_DCRSSM + +#elif defined(INTEL_CXML) + +#define PREFIX __stdcall +#define Epetra_fcd const char *, const unsigned int + +#elif defined(INTEL_MKL) + +#define PREFIX +#define Epetra_fcd const char * + +#endif + +/* All three of these machines use a simple uppercase mangling of Fortran names */ + +/* if F77_FUNC is defined undefine it because we want to redefine */ + +#ifdef F77_FUNC +#undef F77_FUNC +#endif + +#ifdef F77_FUNC_ +#undef F77_FUNC_ +#endif + + +#define F77_FUNC(lcase,UCASE) UCASE +#define F77_FUNC_(lcase,UCASE) UCASE + +#else /* Define Epetra_fcd for all other machines */ + +#define PREFIX +#define Epetra_fcd const char * + +/* Use autoconf's definition of F77_FUNC + unless using old make system */ + +#ifndef HAVE_CONFIG_H + +#ifdef F77_FUNC +#undef F77_FUNC +#endif +#ifdef F77_FUNC_ +#undef F77_FUNC_ +#endif + +#ifdef TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE +#define F77_FUNC(lcase,UCASE) lcase +#define F77_FUNC_(lcase,UCASE) lcase +#else /* TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE not defined*/ +#define F77_FUNC(lcase,UCASE) lcase ## _ +#define F77_FUNC_(lcase,UCASE) lcase ## __ +#endif /* TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE */ + +#endif /* HAVE_CONFIG_H */ + +#endif /* defined(CRAY_T3X) || defined(INTEL_CXML) || defined(INTEL_MKL) */ + +#ifndef CRAY_T3X /* Double declarations already done for the Cray */ + +#define DASUM_F77 F77_FUNC(dasum,DASUM) +#define DAXPY_F77 F77_FUNC(daxpy,DAXPY) +#define DCOPY_F77 F77_FUNC(dcopy,DCOPY) +#define DDOT_F77 F77_FUNC(ddot,DDOT) +#define DNRM2_F77 F77_FUNC(dnrm2,DNRM2) +#define DSCAL_F77 F77_FUNC(dscal,DSCAL) +#define IDAMAX_F77 F77_FUNC(idamax,IDAMAX) +#define DGEMV_F77 F77_FUNC(dgemv,DGEMV) +#define DGER_F77 F77_FUNC(dger,DGER) +#define DTRMV_F77 F77_FUNC(dtrmv,DTRMV) +#define DGEMM_F77 F77_FUNC(dgemm,DGEMM) +#define DSYMM_F77 F77_FUNC(dsymm,DSYMM) +#define DTRMM_F77 F77_FUNC(dtrmm,DTRMM) +#define DTRSM_F77 F77_FUNC(dtrsm,DTRSM) + +#ifdef __GNUC__ /* standard Epetra implementation */ + +#define EPETRA_DCRSMV_F77 F77_FUNC_(epetra_dcrsmv,EPETRA_DCRSMV) +#define EPETRA_DCRSMM_F77 F77_FUNC_(epetra_dcrsmm,EPETRA_DCRSMM) +#define EPETRA_DCRSSV_F77 F77_FUNC_(epetra_dcrssv,EPETRA_DCRSSV) +#define EPETRA_DCRSSM_F77 F77_FUNC_(epetra_dcrssm,EPETRA_DCRSSM) + +#else /* MSE: 3/17/05 - patch for Solaris/OSF/IRIX */ + +#define EPETRA_DCRSMV_F77 F77_FUNC(epetra_dcrsmv,EPETRA_DCRSMV) +#define EPETRA_DCRSMM_F77 F77_FUNC(epetra_dcrsmm,EPETRA_DCRSMM) +#define EPETRA_DCRSSV_F77 F77_FUNC(epetra_dcrssv,EPETRA_DCRSSV) +#define EPETRA_DCRSSM_F77 F77_FUNC(epetra_dcrssm,EPETRA_DCRSSM) +#endif /* __GNUC__ */ + + +/* End of defines for double precision when not on a T3X */ + +#endif + +/* The following defines are good for all platforms */ + + +#define SSCAL_F77 F77_FUNC(sscal,SSCAL) +#define SCOPY_F77 F77_FUNC(scopy,SCOPY) +#define SAXPY_F77 F77_FUNC(saxpy,SAXPY) +#define SDOT_F77 F77_FUNC(sdot,SDOT) +#define SNRM2_F77 F77_FUNC(snrm2,SNRM2) +#define SASUM_F77 F77_FUNC(sasum,SASUM) +#define ISAMAX_F77 F77_FUNC(isamax,ISAMAX) + +#define SGEMV_F77 F77_FUNC(sgemv,SGEMV) +#define SGER_F77 F77_FUNC(sger,SGER) +#define STRMV_F77 F77_FUNC(strmv,STRMV) +#define SGEMM_F77 F77_FUNC(sgemm,SGEMM) +#define SSYMM_F77 F77_FUNC(ssymm,SSYMM) +#define STRMM_F77 F77_FUNC(strmm,STRMM) +#define STRSM_F77 F77_FUNC(strsm,STRSM) + +/* Explicitly define each F77 name for all BLAS kernels */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* Double precision BLAS 1 */ +double PREFIX DASUM_F77(const int* n, const double x[], const int* incx); +void PREFIX DAXPY_F77(const int* n, const double* alpha, const double x[], const int* incx, double y[], const int* incy); +void PREFIX DCOPY_F77(const int* n, const double *x, const int* incx, double *y, const int* incy); +double PREFIX DDOT_F77(const int* n, const double x[], const int* incx, const double y[], const int* incy); +double PREFIX DNRM2_F77(const int* n, const double x[], const int* incx); +void PREFIX DSCAL_F77(const int* n, const double* alpha, double *x, const int* incx); +int PREFIX IDAMAX_F77(const int* n, const double *x, const int* incx); + +/* Single precision BLAS 1 */ +float PREFIX SASUM_F77(const int* n, const float x[], const int* incx); +void PREFIX SAXPY_F77(const int* n, const float* alpha, const float x[], const int* incx, float y[], const int* incy); +void PREFIX SCOPY_F77(const int* n, const float *x, const int* incx, float *y, const int* incy); +float PREFIX SDOT_F77(const int* n, const float x[], const int* incx, const float y[], const int* incy); +float PREFIX SNRM2_F77(const int* n, const float x[], const int* incx); +void PREFIX SSCAL_F77(const int* n, const float* alpha, float *x, const int* incx); +int PREFIX ISAMAX_F77(const int* n, const float *x, const int* incx); + +/* Double precision BLAS 2 */ +void PREFIX DGEMV_F77(Epetra_fcd, const int* m, const int* n, const double* alpha, const double A[], const int* lda, + const double x[], const int* incx, const double* beta, double y[], const int* incy); +void PREFIX DTRMV_F77(Epetra_fcd, Epetra_fcd, Epetra_fcd, const int *n, + const double *a, const int *lda, double *x, const int *incx); +void PREFIX DGER_F77(const int *m, const int *n, const double *alpha, const double *x, const int *incx, const double *y, + const int *incy, double *a, const int *lda); + + +/* Single precision BLAS 2 */ +void PREFIX SGEMV_F77(Epetra_fcd, const int* m, const int* n, const float* alpha, const float A[], const int* lda, + const float x[], const int* incx, const float* beta, float y[], const int* incy); +void PREFIX STRMV_F77(Epetra_fcd, Epetra_fcd, Epetra_fcd, const int *n, + const float *a, const int *lda, float *x, const int *incx); +void PREFIX SGER_F77(const int *m, const int *n, const float *alpha, const float *x, const int *incx, const float *y, + const int *incy, float *a, const int *lda); + +/* Double precision BLAS 3 */ +void PREFIX DGEMM_F77(Epetra_fcd, Epetra_fcd, const int *m, const int * + n, const int *k, const double *alpha, const double *a, const int *lda, + const double *b, const int *ldb, const double *beta, double *c, const int *ldc); +void PREFIX DSYMM_F77(Epetra_fcd, Epetra_fcd, const int *m, const int * n, + const double *alpha, const double *a, const int *lda, + const double *b, const int *ldb, const double *beta, double *c, const int *ldc); +void PREFIX DTRMM_F77(Epetra_fcd, Epetra_fcd, Epetra_fcd, Epetra_fcd, + const int *m, const int *n, const double *alpha, const double *a, const int * lda, double *b, const int *ldb); +void PREFIX DTRSM_F77(Epetra_fcd, Epetra_fcd, Epetra_fcd, Epetra_fcd, + const int *m, const int *n, const double *alpha, const double *a, const int * + lda, double *b, const int *ldb); +void PREFIX EPETRA_DCRSMV_F77(const int *, const int *, const int *, const double *, const int *, + const int *, double *, double *); +void PREFIX EPETRA_DCRSMM_F77(const int *, const int *, const int *, const double *, const int *, + const int *, double *, int *, double *, int *, int *); +void PREFIX EPETRA_DCRSSV_F77(const int *, const int *, const int *, const int *, const int *, + const int *, const double *, const int *, const int *, double *, + double *, const int *); +void PREFIX EPETRA_DCRSSM_F77(const int *, const int *, const int *, const int *, const int *, + const int *, const double *, const int *, const int *, double *, + const int *, double *, const int *, const int *, const int *); + +/* Single precision BLAS 3 */ +void PREFIX SGEMM_F77(Epetra_fcd, Epetra_fcd, const int *m, const int * + n, const int *k, const float *alpha, const float *a, const int *lda, + const float *b, const int *ldb, const float *beta, float *c, const int *ldc); +void PREFIX SSYMM_F77(Epetra_fcd, Epetra_fcd, const int *m, const int * n, + const float *alpha, const float *a, const int *lda, + const float *b, const int *ldb, const float *beta, float *c, const int *ldc); +void PREFIX STRMM_F77(Epetra_fcd, Epetra_fcd, Epetra_fcd, Epetra_fcd, + const int *m, const int *n, const float *alpha, const float *a, const int * lda, float *b, const int *ldb); +void PREFIX STRSM_F77(Epetra_fcd, Epetra_fcd, Epetra_fcd, Epetra_fcd, + const int *m, const int *n, const float *alpha, const float *a, const int * + lda, float *b, const int *ldb); + +void PREFIX XERBLA_F77(Epetra_fcd, int *info); + +#ifdef __cplusplus +} +#endif + +#endif /* EPETRA_BLAS_WRAPPERS_H */ diff --git a/fastlib/trilinos/include/Epetra_BasicDirectory.h b/fastlib/trilinos/include/Epetra_BasicDirectory.h new file mode 100644 index 0000000000..c155ba8ca0 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_BasicDirectory.h @@ -0,0 +1,176 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_BASICDIRECTORY_H +#define EPETRA_BASICDIRECTORY_H + +#include "Epetra_Object.h" +#include "Epetra_Directory.h" +#include "Epetra_Map.h" + +//! Epetra_BasicDirectory: This class allows Epetra_Map objects to reference non-local elements. + +/*! For Epetra_BlockMap objects, a Epetra_Directory object must be created to allow referencing + of non-local elements. The Epetra_BasicDirectory produces and contains a uniform linear + Epetra_BlockMap and a ProcList_ allowing blocks of non-local elements to be accessed + by dereferencing throught the Epetra_BasicDirectory. + + This class currently has one constructor, taking a Epetra_BlockMap object. + +*/ + +class Epetra_BasicDirectory: public virtual Epetra_Directory { + + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_BasicDirectory constructor + Epetra_BasicDirectory(const Epetra_BlockMap & Map ); + + //! Epetra_BasicDirectory copy constructor. + + Epetra_BasicDirectory(const Epetra_BasicDirectory& Directory); + + //! Epetra_BasicDirectory destructor. + + virtual ~Epetra_BasicDirectory(void); + //@} + + //! @name Query method + //@{ + //! GetDirectoryEntries : Returns proc and local id info for non-local map entries + /*! Given a list of Global Entry IDs, this function returns the list of + processor IDs and local IDs on the owning processor that correspond + to the list of entries. If LocalEntries is 0, then local IDs are + not returned. If EntrySizes is nonzero, it will contain a list of corresponding + element sizes for the requested global entries. + \param In + NumEntries - Number of Global IDs being passed in. + \param In + GlobalEntries - List of Global IDs being passed in. + \param InOut + Procs - User allocated array of length at least NumEntries. On return contains list of processors + owning the Global IDs in question. If any of the GIDs is shared by more than + one processor, then the lowest-numbered processor is listed in this array, unless the optional + argument 'high_rank_sharing_procs' is given as true. + \param InOut + LocalEntries - User allocated array of length at least NumEntries. On return contains the local ID of + the global on the owning processor. If LocalEntries is zero, no local ID information is returned. + \param InOut + EntrySizes - User allocated array of length at least NumEntries. On return contains the size of the + object associated with this global ID. If LocalEntries is zero, no size information is returned. + + \param In + high_rank_sharing_procs Optional argument, defaults to true. If any GIDs appear on multiple + processors (referred to as "sharing procs"), this specifies whether the lowest-rank proc or the + highest-rank proc is chosen as the "owner". + + \return Integer error code, set to 0 if successful. + */ + int GetDirectoryEntries( const Epetra_BlockMap& Map, + const int NumEntries, + const int * GlobalEntries, + int * Procs, + int * LocalEntries, + int * EntrySizes, + bool high_rank_sharing_procs=false) const; + + //!GIDsAllUniquelyOwned: returns true if all GIDs appear on just one processor. + /*! If any GIDs are owned by multiple processors, returns false. + */ + bool GIDsAllUniquelyOwned() const; + //@} + + //! @name I/O Methods + //@{ + //! Print method + virtual void Print(ostream & os) const; + //@} + + private: + Epetra_BasicDirectory& operator=(const Epetra_BasicDirectory& src); + + void create_ProcListArrays(); + + void addProcToList(int proc, int LID); + + //! Generate: Sets up Directory tables. + int Generate(const Epetra_BlockMap& Map); + + //! Returns the Epetra_Map containing the directory + const Epetra_Map & DirectoryMap() const {return(*DirectoryMap_);}; + + Epetra_Map* DirectoryMap_; + + //ProcList_ is a list containing the associated processor for each + //directory entry. If any directory entry has more than one associated + //processor, then the corresponding ProcList_ entry will be the lowest- + //numbered of those processors. In that case, refer to ProcListLists_ + //for more info. + + int * ProcList_; + + //ProcListLists_ will usually be unallocated, and set to NULL. But if + //at least one directory entry is associcated with more than one proc, + //then ProcListLists_ is a list of lists -- it holds, for each + //directory-entry, a list of processors. + //But even then, it will have a NULL list for all directory entries that + //are associated with only one processor. + // + //Each list's length will be stored in ProcListLens_. + //Example: + // + //if (numProcLists_ > 0) { + // int entry_LID = DirectoryMap_->LID(GID); + // + // for(int i=0; i +
  • ExtractMyRowCopy: Provide a row of values and indices for a specified local row. +
  • ExtractMyEntryView (const and non-const versions): Provide the memory address of the ith nonzero term stored on the + calling processor, along with its corresponding local row and column index, where i goes from 0 to the NumMyNonzeros()-1. + The order in which the nonzeros are traversed is not specified and is up to the adapter implementation. +
  • NumMyRowEntries: Provide the number of entries for a specified local row. + + + An alternative is possible if you do not want to provide a non-trivial implementation of the ExtraMyEntryView + methods (See Epetra_VbrRowMatrix for and example): +
      +
    1. Implement ExtractMyRowCopy and NumMyRowEntries as above. +
    2. Implement ExtractMyEntryView (both versions) returning a -1 integer code with no other executable code. +
    3. Implement the RightScale and LeftScale methods non-trivially. +
    + +In addition, most adapters will probably re-implement the Multiply() method and perhaps the Solve() method, although one or the other +may be implemented to return -1, signaling that there is no valid implementation. By default, the Multiply() method is implemented using +ExtractMyRowCopy, which can usual be improved upon. By default Solve() and ApplyInverse() are implemented to return -1 (not implemented). + +All other implemented methods in Epetra_BasicRowMatrix should not exhibit a signficant performance degradation, either because they are relatively +small and fast, or because they are not a significant portion of the runtime for most codes. All methods are virtual, so they can be re-implemented +by the adapter. + +In addition to implementing the above methods, an adapter must inherit the Epetra_BasicRowMatrix interface and call the Epetra_BasicRowMatrix +constructor as part of the adapter constructor. There are two constructors. The first requires the user to pass in the RowMap and ColMap, both +of which are Epetra_Map objects. On each processor the RowMap (ColMap) must contain the global IDs (GIDs) of the rows (columns) that the processor cares about. +The first constructor requires only these two maps, assuming that the RowMap will also serve as the DomainMap and RangeMap. In this case, the +RowMap must be 1-to-1, meaning that if a global ID appears on one processor, it appears only once on that processor and does not appear on any other +processor. For many sparse matrix data structures, it is the case that a given row is completely owned by one processor and that the global matrix +is square. The first constructor is for this situation. + +The second constructor allows the caller to specify all four maps. In this case the DomainMap, the layout of multivectors/vectors that are in the +domain of the matrix (the x vector if computing y = A*x), must be 1-to-1. Also, the RangeMap, the layout of y must be 1-to-1. The RowMap and ColMap +do not need to be 1-to-1, but the GIDs must be found in the RangeMap and DomainMap, respectively. + +Note that Epetra_Operator is a base class for Epetra_RowMatrix, so any adapter +for Epetra_BasicRowMatrix (or Epetra_RowMatrix) is also an adapter for Epetra_Operator. + +An example of how to provide an adapter for Epetra_BasicRowMatrix can be found by looking at Epetra_JadMatrix. + +*/ + +class Epetra_BasicRowMatrix: public Epetra_CompObject, public Epetra_Object, public virtual Epetra_RowMatrix { + + public: + + //! @name Constructor/Destructor + //@{ + //! Epetra_BasicRowMatrix constuctor. + /* This constructor requires a valid Epetra_Comm object as its only argument. The constructor will use Comm to build + Epetra_Maps objects: RowMap, ColMap, DomainMap and RangeMap. However, these will be zero-length (trivial) maps that + \e must be reset by calling one of the two SetMap() methods listed below. + \param Comm (In) An Epetra_Comm containing a valid Comm object. + */ + Epetra_BasicRowMatrix(const Epetra_Comm & Comm); + + //! Epetra_BasicRowMatrix Destructor + virtual ~Epetra_BasicRowMatrix(); + //@} + + //! @name Setup functions + //@{ + //! Set maps (Version 1); call this function or the next, but not both. + /* This method takes a row and column map. On each processor these maps describe the global rows and columns, resp, + that the processor will care about. Note that the ColMap does not have to be one-to-one. In other words, a column ID can appear + on more than one processor. The RowMap \e must be 1-to-1. + \param RowMap (In) An Epetra_Map containing on each processor a list of GIDs of rows that the processor cares about. + \param ColMap (In) An Epetra_Map containing on each processor a list of GIDs of columns that the processor cares about. + + In this method, the domain and range maps are assumed to be the same as the row map. Note that this requires that + the global matrix be square. If the matrix is not square, or the domain vectors or range vectors do not have the same layout + as the rows, then the second constructor should be called. + */ + void SetMaps(const Epetra_Map & RowMap, const Epetra_Map & ColMap); + + //! Set maps (Version 2); call this function or the previous, but not both. + /* This constructor takes a row, column, domain and range map. On each processor these maps describe the global rows, columns, domain + and range, resp, that the processor will care about. The domain and range maps must be one-to-one, but note that the row and column + maps do not have to be one-to-one. In other words, a row ID can appear + on more than one processor, as can a column ID. + \param RowMap (In) An Epetra_Map containing on each processor a list of GIDs of rows that the processor cares about. + \param ColMap (In) An Epetra_Map containing on each processor a list of GIDs of columns that the processor cares about. + \param DomainMap (In) An Epetra_Map describing the distribution of domain vectors and multivectors. + \param RangeMap (In) An Epetra_Map describing the distribution of range vectors and multivectors. + + */ + void SetMaps(const Epetra_Map & RowMap, const Epetra_Map & ColMap, + const Epetra_Map & DomainMap, const Epetra_Map & RangeMap); + + //@} + + + //! @name User-required implementation methods + //@{ + + //! Returns a copy of the specified local row in user-provided arrays. + /*! + \param MyRow (In) - Local row to extract. + \param Length (In) - Length of Values and Indices. + \param NumEntries (Out) - Number of nonzero entries extracted. + \param Values (Out) - Extracted values for this row. + \param Indices (Out) - Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful, set to -1 if MyRow not valid, -2 if Length is too short (NumEntries will have required length). + */ + virtual int ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, double *Values, int * Indices) const = 0; + + //! Returns a reference to the ith entry in the matrix, along with its row and column index. + /*! + \param CurEntry (In) - Index of local entry (from 0 to NumMyNonzeros()-1) to extract. + \param Value (Out) - Extracted reference to current values. + \param RowIndex (Out) - Row index for current entry. + \param ColIndex (Out) - Column index for current entry. + + \return Integer error code, set to 0 if successful, set to -1 if CurEntry not valid. + */ + virtual int ExtractMyEntryView(int CurEntry, double * & Value, int & RowIndex, int & ColIndex) = 0; + + //! Returns a const reference to the ith entry in the matrix, along with its row and column index. + /*! + \param CurEntry (In) - Index of local entry (from 0 to NumMyNonzeros()-1) to extract. + \param Value (Out) - Extracted reference to current values. + \param RowIndex (Out) - Row index for current entry. + \param ColIndex (Out) - Column index for current entry. + + \return Integer error code, set to 0 if successful, set to -1 if CurEntry not valid. + */ + virtual int ExtractMyEntryView(int CurEntry, double const * & Value, int & RowIndex, int & ColIndex) const = 0; + + //! Return the current number of values stored for the specified local row. + /*! Similar to NumMyEntries() except NumEntries is returned as an argument + and error checking is done on the input value MyRow. + \param MyRow (In) - Local row. + \param NumEntries (Out) - Number of nonzero values. + + \return Integer error code, set to 0 if successful, set to -1 if MyRow not valid. + */ + virtual int NumMyRowEntries(int MyRow, int & NumEntries) const = 0; + //@} + + //! @name Computational methods + //@{ + + //! Returns the result of a Epetra_BasicRowMatrix multiplied by a Epetra_MultiVector X in Y. + /*! + \param TransA (In) - If true, multiply by the transpose of matrix, otherwise just use matrix. + \param X (Out) - An Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Y (Out) - An Epetra_MultiVector of dimension NumVectorscontaining result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + //! Returns the result of a Epetra_BasicRowMatrix solve with a Epetra_MultiVector X in Y (not implemented). + /*! + \param Upper (In) - If true, solve Ux = y, otherwise solve Lx = y. + \param Trans (In) - If true, solve transpose problem. + \param UnitDiagonal (In) - If true, assume diagonal is unit (whether it's stored or not). + \param X (In) - An Epetra_MultiVector of dimension NumVectors to solve for. + \param Y (Out) - An Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Solve(bool Upper, bool Trans, bool UnitDiagonal, + const Epetra_MultiVector& X, + Epetra_MultiVector& Y) const + { + (void)Upper; + (void)Trans; + (void)UnitDiagonal; + (void)X; + (void)Y; + return(-1); + } + + //! Returns a copy of the main diagonal in a user-provided vector. + /*! + \param Diagonal (Out) - Extracted main diagonal. + + \return Integer error code, set to 0 if successful. + */ + virtual int ExtractDiagonalCopy(Epetra_Vector & Diagonal) const; + + //! Computes the sum of absolute values of the rows of the Epetra_BasicRowMatrix, results returned in x. + /*! The vector x will return such that x[i] will contain the inverse of sum of the absolute values of the + \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. Using the resulting vector from this function as input to LeftScale() + will make the infinity norm of the resulting matrix exactly 1. + \param x (Out) - An Epetra_Vector containing the row sums of the \e this matrix. + \warning It is assumed that the distribution of x is the same as the rows of \e this. + + \return Integer error code, set to 0 if successful. + */ + virtual int InvRowSums(Epetra_Vector& x) const; + + //! Scales the Epetra_BasicRowMatrix on the left with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the row number of A + and j denotes the column number of A. + \param x (In) - An Epetra_Vector to solve for. + + \return Integer error code, set to 0 if successful. + */ + virtual int LeftScale(const Epetra_Vector& x); + + //! Computes the sum of absolute values of the columns of the Epetra_BasicRowMatrix, results returned in x. + /*! The vector x will return such that x[j] will contain the inverse of sum of the absolute values of the + \e this matrix will be sca such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. Using the resulting vector from this function as input to + RighttScale() will make the one norm of the resulting matrix exactly 1. + \param x (Out) - An Epetra_Vector containing the column sums of the \e this matrix. + \warning It is assumed that the distribution of x is the same as the rows of \e this. + + \return Integer error code, set to 0 if successful. + */ + virtual int InvColSums(Epetra_Vector& x) const; + + //! Scales the Epetra_BasicRowMatrix on the right with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. + \param x (In) - The Epetra_Vector used for scaling \e this. + + \return Integer error code, set to 0 if successful. + */ + virtual int RightScale(const Epetra_Vector& x); + //@} + + //! @name Matrix Properties Query Methods + //@{ + + + //! If FillComplete() has been called, this query returns true, otherwise it returns false, presently always returns true. + virtual bool Filled() const {return(true);} + + //! If matrix is lower triangular, this query returns true, otherwise it returns false. + bool LowerTriangular() const {if (!HaveNumericConstants_) ComputeNumericConstants(); return(LowerTriangular_);} + + //! If matrix is upper triangular, this query returns true, otherwise it returns false. + virtual bool UpperTriangular() const {if (!HaveNumericConstants_) ComputeNumericConstants(); return(UpperTriangular_);} + + //@} + + //! @name Atribute access functions + //@{ + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f]. + + \warning This method is supported if and only if the Epetra_RowMatrix Object that was used to create this supports this method. + + */ + virtual double NormInf() const{if (!HaveNumericConstants_) ComputeNumericConstants(); return(NormInf_);} + + //! Returns the one norm of the global matrix. + /* Returns the quantity \f$ \| A \|_1\f$ such that + \f[\| A \|_1= \max_{1\lej\len} \sum_{i=1}^m |a_{ij}| \f]. + + \warning This method is supported if and only if the Epetra_RowMatrix Object that was used to create this supports this method. + + */ + virtual double NormOne() const{if (!HaveNumericConstants_) ComputeNumericConstants(); return(NormOne_);} + + //! Returns the number of nonzero entries in the global matrix. + /* Note that if the data decomposition is defined such that some nonzeros + appear on multiple processors, then those nonzeros will be counted + multiple times. + */ + virtual int NumGlobalNonzeros() const{if (!HaveStructureConstants_) ComputeStructureConstants(); return(NumGlobalNonzeros_);} + + //! Returns the number of global matrix rows. + virtual int NumGlobalRows() const {return(OperatorRangeMap().NumGlobalPoints());} + + //! Returns the number of global matrix columns. + virtual int NumGlobalCols() const {return(OperatorDomainMap().NumGlobalPoints());} + + //! Returns the number of global nonzero diagonal entries. + virtual int NumGlobalDiagonals() const{return(OperatorDomainMap().NumGlobalPoints());} + + //! Returns the number of nonzero entries in the calling processor's portion of the matrix. + virtual int NumMyNonzeros() const{if (!HaveStructureConstants_) ComputeStructureConstants(); return(NumMyNonzeros_);} + + //! Returns the number of matrix rows owned by the calling processor. + virtual int NumMyRows() const {return(OperatorRangeMap().NumMyPoints());} + + //! Returns the number of matrix columns owned by the calling processor. + virtual int NumMyCols() const {return(RowMatrixColMap().NumMyPoints());} + + //! Returns the number of local nonzero diagonal entries. + virtual int NumMyDiagonals() const {return(OperatorRangeMap().NumMyPoints());} + + //! Returns the maximum number of nonzero entries across all rows on this processor. + virtual int MaxNumEntries() const{ if (!HaveStructureConstants_) ComputeStructureConstants(); return(MaxNumEntries_);} + + //! Returns the Epetra_Map object associated with the domain of this operator. + virtual const Epetra_Map & OperatorDomainMap() const {return(OperatorDomainMap_);} + + //! Returns the Epetra_Map object associated with the range of this operator (same as domain). + virtual const Epetra_Map & OperatorRangeMap() const {return(OperatorRangeMap_);} + + //! Implement the Epetra_SrcDistObjec::Map() function. + virtual const Epetra_BlockMap& Map() const {return(RowMatrixRowMap());} + + //! Returns the Row Map object needed for implementing Epetra_RowMatrix. + virtual const Epetra_Map & RowMatrixRowMap() const {return(RowMatrixRowMap_);} + + //! Returns the Column Map object needed for implementing Epetra_RowMatrix. + virtual const Epetra_Map & RowMatrixColMap() const {return(RowMatrixColMap_);} + + //! Returns the Epetra_Import object that contains the import operations for distributed operations. + virtual const Epetra_Import * RowMatrixImporter() const {return(Importer_);} + + //! Returns a pointer to the Epetra_Comm communicator associated with this matrix. + virtual const Epetra_Comm & Comm() const {return(*Comm_);} + //@} + + + //! @name I/O Methods + //@{ + + //! Print method + virtual void Print(ostream & os) const; + //@} + + //! @name Additional methods required to support the Epetra_RowMatrix interface + //@{ + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param UseTranspose (In) - If true, multiply by the transpose of operator, otherwise just use operator. + + \return Always returns 0. + */ + virtual int SetUseTranspose(bool UseTranspose) {UseTranspose_ = UseTranspose; return(0);} + + //! Returns a character string describing the operator + virtual const char* Label() const {return(Epetra_Object::Label());} + + //! Returns the result of a Epetra_RowMatrix applied to a Epetra_MultiVector X in Y. + /*! + \param X (In) - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Y (Out) - A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { + return(Multiply(Epetra_BasicRowMatrix::UseTranspose(), X, Y));} + + //! Returns the result of a Epetra_RowMatrix inverse applied to an Epetra_MultiVector X in Y. + /*! + + \param X (In) - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Y (Out) - A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code = -1. + \warning This method is NOT supported. + */ + virtual int ApplyInverse(const Epetra_MultiVector& X, + Epetra_MultiVector& Y) const + { + (void)X; + (void)Y; + return(-1); + } + + //! Returns true because this class can compute an Inf-norm. + bool HasNormInf() const {return(true);} + + //! Returns the current UseTranspose setting. + virtual bool UseTranspose() const {return(UseTranspose_);} + + //@} + + //! @name Additional accessor methods + //@{ + + //! Returns the Epetra_Import object that contains the import operations for distributed operations, returns zero if none. + /*! If RowMatrixColMap!=OperatorDomainMap, then this method returns a pointer to an Epetra_Import object that imports objects + from an OperatorDomainMap layout to a RowMatrixColMap layout. This operation is needed for sparse matrix-vector + multiplication, y = Ax, to gather x elements for local multiplication operations. + + If RowMatrixColMap==OperatorDomainMap, then the pointer will be returned as 0. + + \return Raw pointer to importer. This importer will be valid as long as the Epetra_RowMatrix object is valid. + */ + virtual const Epetra_Import* Importer() const {return(Importer_);} + + //! Returns the Epetra_Export object that contains the export operations for distributed operations, returns zero if none. + /*! If RowMatrixRowMap!=OperatorRangeMap, then this method returns a pointer to an Epetra_Export object that exports objects + from an RowMatrixRowMap layout to a OperatorRangeMap layout. This operation is needed for sparse matrix-vector + multiplication, y = Ax, to scatter-add y elements generated during local multiplication operations. + + If RowMatrixRowMap==OperatorRangeMap, then the pointer will be returned as 0. For a typical Epetra_RowMatrix object, + this pointer will be zero since it is often the case that RowMatrixRowMap==OperatorRangeMap. + + \return Raw pointer to exporter. This exporter will be valid as long as the Epetra_RowMatrix object is valid. + */ + virtual const Epetra_Export* Exporter() const {return(Exporter_);} + + //@} + + protected: + + //! @name Post-construction modifications + //@{ + //! Update the constants associated with the structure of the matrix: Call only if structure changes from the initial RowMatrix. + /* Several constants are pre-computed to save excess computations. However, if the structure of the + problem changes, specifically if the nonzero count in any given row changes, then this function should be called + to update these constants. + */ + virtual void ComputeStructureConstants() const; + //! Update the constants associated with the values of the matrix: Call only if values changes from the initial RowMatrix. + /* Several numeric constants are pre-computed to save excess computations. However, if the values of the + problem change, then this function should be called to update these constants. + */ + virtual void ComputeNumericConstants() const; + //@} + + void Setup(); + void UpdateImportVector(int NumVectors) const; + void UpdateExportVector(int NumVectors) const; + void SetImportExport(); + Epetra_Comm * Comm_; + Epetra_Map OperatorDomainMap_; + Epetra_Map OperatorRangeMap_; + Epetra_Map RowMatrixRowMap_; + Epetra_Map RowMatrixColMap_; + + mutable int NumMyNonzeros_; + mutable int NumGlobalNonzeros_; + mutable int MaxNumEntries_; + mutable double NormInf_; + mutable double NormOne_; + int NumMyRows_; + int NumMyCols_; + + bool UseTranspose_; + bool HasNormInf_; + mutable bool LowerTriangular_; + mutable bool UpperTriangular_; + mutable bool HaveStructureConstants_; + mutable bool HaveNumericConstants_; + mutable bool HaveMaps_; + + + mutable Epetra_MultiVector * ImportVector_; + mutable Epetra_MultiVector * ExportVector_; + Epetra_Import * Importer_; + Epetra_Export * Exporter_; + +}; +#endif /* EPETRA_BASICROWMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_BlockMap.h b/fastlib/trilinos/include/Epetra_BlockMap.h new file mode 100644 index 0000000000..4ba50863a8 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_BlockMap.h @@ -0,0 +1,535 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_BLOCKMAP_H +#define EPETRA_BLOCKMAP_H + +#include "Epetra_Object.h" +#include "Epetra_BlockMapData.h" + + +//! Epetra_BlockMap: A class for partitioning block element vectors and matrices. + +/*! It is often the case that multiple matrix and vector objects have an identical distribution + of elements on a parallel machine. The Epetra_BlockMap class keeps information that describes + this distribution for matrices and vectors that have block elements. The definition of an + element can vary depending on the situation. For vectors (and multi-vectors), an element + is a span of one or more contiguous entries. For matrices, it is a span of one or more matrix rows. + More generally, an element in the BlockMap class is an ordered list of points. (NOTE: + Points do not have global ID's.) Two additional definitions useful in understanding + the BlockMap class follow: +
      +
    • BlockMap - A distributed ordered list of elements. +
    • First Point - First ordered point in an element +
    + + This class has a variety of constructors that can be separated into two categories: +
      +
    1. Fixed element size constructors: + All map elements have an identical size. + This corresponds to a block partitioning of matrices and vectors where the element + size is the same for all elements. A common example is multiple degrees of freedom + per mesh node in finite element computations where the number of degrees of + freedom is the same for all nodes. +
    2. Variable element size constructor: + Map element sizes may vary and are individually defined via a list of element sizes. + This is the most general case and corresponds to a variable block partitioning of the + matrices and vectors. A common example is + multiple degrees of freedom per mesh node in finite element computations where the + number of degrees of freedom varies. This happens, for example, if regions have differing + material types or there are chemical reactions in the simulation. +
    + + Epetra_BlockMap allows the storage and retrieval of the following information. Depending on the + constructor that is used, some of the information is defined by the user and some is + determined by the constructor. Once an Epetra_BlockMap is constructed any of the following can + be obtained + by calling a query function that has the same name as the attribute, e.g. to get the + value of NumGlobalElements, you can call a function NumGlobalElements(). For attributes that + are lists, the query functions return the list values in a user allocated array. + +
      +
    • NumGlobalElements - The total number of elements across all processors. If this parameter and + NumMyElements are both passed in to the constructor, one of the three cases will apply: +
        +
      1. If NumGlobalElements = NumMyElements (and not equal to zero) + the map is defined to be a local replicated + map. In this case, objects constructed using this map will be identically replicated across + all processors in the communicator. +
      2. If NumGlobalElements = -1 and NumMyElements is passed in then NumGlobalElements will + be computed as the sum of NumMyElements across all processors. +
      3. If neither of the above is true, NumGlobalElements will be checked against the sum of + NumMyElements across all processors. An error is issued if the comparison is not equal. +
      +
    • NumMyElements - The number of elements owned by the calling processor. +
    • MyGlobalElements - A list of length NumMyElements that contains the global element IDs + of the elements owned by the calling processor. +
    • ElementSize - The size of elements if the size of all elements is the same. + This will be the case if the query function ConstantElementSize() returns true. + Otherwise this value will be set to zero. +
    • ElementSizeList - A list of the element sizes for elements owned by the calling + processor. This list is always accessible, even if the element sizes are all one + or of constant value. However, in these cases, the ElementSizeList will not be + generated unless a query for the list is called. +
    • IndexBase - The base integer value for indexed array references. Typically this is 0 + for C/C++ and 1 for Fortran, but it can be set to any integer value. +
    • Comm - The Epetra_Comm communicator. This communicator can in turn be queried for + processor rank and size information. +
    + + + In addition to the information above that is passed in to or created by the Epetra_BlockMap constructor, + the following attributes are computed and available via query to the user using the same scheme + as above, e.g., use NumGlobalPoints() to get the value of NumGlobalPoints. + +
      +
    • NumGlobalPoints - The total number of points across all processors. +
    • NumMyPoints - The number of points on the calling processor. +
    • MinAllGID - The minimum global index value across all processors. +
    • MaxAllGID - The maximum global index value across all processors. +
    • MinMyGID - The minimum global index value on the calling processor. +
    • MaxMyGID - The maximum global index value on the calling processor. +
    • MinLID - The minimum local index value on the calling processor. +
    • MaxLID - The maximum local index value on the calling processor. +
    • MinElementSize - The minimum element size across all processors. +
    • MaxElementSize - The maximum element size across all processors. +
    + + The following functions allow boolean tests for certain properties. + +
      +
    • ConstantElementSize() - Returns true if the element size for this map is the same + for all elements. +
    • LinearMap() - Returns true if the elements are distributed linear across processors, i.e., + processor 0 gets the first n/p elements, processor 1 gets the next n/p elements, etc. where + n is the number of elements and p is the number of processors. +
    • DistributedGlobal() - Returns true if the element space of the map spans more than one processor. + This will be true in most cases, but will be false on in serial and for objects + that are created via the derived Epetra_LocalMap class. +
    + + \warning A Epetra_Comm object is required for all Epetra_BlockMap constructors. + + \bf {error handling} + + Most methods in Epetra_BlockMap return an integer error code. If the error code is 0, then no error occurred. + If > 0 then a warning error occurred. If < 0 then a fatal error occurred. + + Epetra_BlockMap constructors will throw an exception of an error occurrs. These exceptions will alway be negative integer values + as follows: +
      +
    1. -1 NumGlobalElements < -1. Should be >= -1 (Should be >= 0 for first BlockMap constructor). +
    2. -2 NumMyElements < 0. Should be >= 0. +
    3. -3 ElementSize <= 0. Should be > 0. +
    4. -4 Invalid NumGlobalElements. Should equal sum of MyGlobalElements, or set to -1 to compute automatically. +
    5. -5 Minimum global element index is less than index base. +
    6. -99 Internal Epetra_BlockMap error. Contact developer. +
    + + For robust code, Epetra_BlockMap constructor calls should be caught using the try {...} catch {...} mechanism. For example: + +\verbatim + try { + + Epetra_BlockMap * map = new Epetra_BlockMap(NumGlobalElements, ElementSize, IndexBase, Comm); + } + catch (int Error) { + if (Error==-1) { // handle error } + if (Error==-2) ... +\endverbatim + + + \note + { + In the current implementation, Epetra_BlockMap is the base class for: +
      +
    • Epetra_Map. +
    • Epetra_LocalBlockMap. +
    + } + +*/ + +class Epetra_BlockMap: public Epetra_Object { + friend class Epetra_Directory; + friend class Epetra_LocalMap; + public: + //! @name Constructors/destructors + //@{ + //! Epetra_BlockMap constructor for a Epetra-defined uniform linear distribution of constant size elements. + /*! Creates a map that distributes NumGlobalElements elements evenly across all processors in the + Epetra_Comm communicator. If NumGlobalElements does not divide exactly into the number of processors, + the first processors in the communicator get one extra element until the remainder is gone. + + The elements are defined to have a constant fixed size specified by ElementSize. + + \param In + NumGlobalElements - Number of elements to distribute. + + \param In + ElementSize - Number of points or vector entries per element. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_BlockMap object. + + */ + Epetra_BlockMap(int NumGlobalElements, int ElementSize, int IndexBase, const Epetra_Comm& Comm); + + //! Epetra_BlockMap constructor for a user-defined linear distribution of constant size elements. + /*! Creates a map that puts NumMyElements on the calling processor. If + NumGlobalElements=-1, the number of global elements will be + the computed sum of NumMyElements across all processors in the + Epetra_Comm communicator. + + The elements are defined to have a constant fixed size specified by ElementSize. + + \param In + NumGlobalElements - Number of elements to distribute. Must be + either -1 or equal to the computed sum of NumMyElements across all + processors in the Epetra_Comm communicator. + + \param In + NumMyElements - Number of elements owned by the calling processor. + + \param In + ElementSize - Number of points or vector entries per element. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_BlockMap object. + + */ + Epetra_BlockMap(int NumGlobalElements, int NumMyElements, + int ElementSize, int IndexBase, const Epetra_Comm& Comm); + + //! Epetra_BlockMap constructor for a user-defined arbitrary distribution of constant size elements. + /*! Creates a map that puts NumMyElements on the calling processor. The indices of the elements + are determined from the list MyGlobalElements. If NumGlobalElements=-1, + the number of global elements will be the computed sum of NumMyElements + across all processors in the Epetra_Comm communicator. + + The elements are defined to have a constant fixed size specified by ElementSize. + + \param In + NumGlobalElements - Number of elements to distribute. Must be + either -1 or equal to the computed sum of NumMyElements across all + processors in the Epetra_Comm communicator. + + \param In + NumMyElements - Number of elements owned by the calling processor. + + \param In + MyGlobalElements - Integer array of length NumMyElements. The ith entry contains the + global index value of the ith element on this processor. Index values are not required to + be contiguous on a processor, or to be within the range of 0 to NumGlobalElements. As + long as the index values are consistently defined and used, any set of NumGlobalElements + distinct integer values is acceptable. + + \param In + ElementSize - Number of points or vector entries per element. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_BlockMap object. + + */ + Epetra_BlockMap(int NumGlobalElements, int NumMyElements, + const int *MyGlobalElements, + int ElementSize, int IndexBase, const Epetra_Comm& Comm); + + //! Epetra_BlockMap constructor for a user-defined arbitrary distribution of variable size elements. + /*! Creates a map that puts NumMyElements on the calling processor. If + NumGlobalElements=-1, the number of global elements will be + the computed sum of NumMyElements across all processors in the + Epetra_Comm communicator. + + The elements are defined to have a variable size defined by ElementSizeList. + + \param In + NumGlobalElements - Number of elements to distribute. Must be + either -1 or equal to the computed sum of NumMyElements across all + processors in the Epetra_Comm communicator. + + \param In + NumMyElements - Number of elements owned by the calling processor. + + \param In + MyGlobalElements - Integer array of length NumMyElements. The ith entry contains the + global index value of the ith element on this processor. Index values are not required to + be contiguous on a processor, or to be within the range of 0 to NumGlobalElements. As + long as the index values are consistently defined and used, any set of NumGlobalElements + distinct integer values is acceptable. + + \param In + ElementSizeList - A list of the element sizes for elements owned by the calling + processor. The ith entry contains the element size of the ith element on this processor. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_BlockMap object. + + */ + Epetra_BlockMap(int NumGlobalElements, int NumMyElements, + const int *MyGlobalElements, + const int *ElementSizeList, int IndexBase, + const Epetra_Comm& Comm); + + //! Epetra_BlockMap copy constructor. + Epetra_BlockMap(const Epetra_BlockMap& map); + + //! Epetra_BlockMap destructor. + virtual ~Epetra_BlockMap(void); + //@} + + //! @name Local/Global ID accessor methods + //@{ + //! Returns the processor IDs and corresponding local index value for a given list of global indices + /*! For each element (GID) of a given list of global element numbers (stored in GIDList) of length NumIDs, + this function returns (in PIDList) the with processor that owns the GID for this map and returns the + local index (in LIDList) of the GID on that processor. + */ + int RemoteIDList(int NumIDs, const int * GIDList, int * PIDList, int * LIDList) const { + return(RemoteIDList(NumIDs, GIDList, PIDList, LIDList, 0)); + }; + + //! Returns the processor IDs, corresponding local index value, and element size for a given list of global indices + /*! For each element (GID) of a given a list of global element numbers (stored in GIDList) of length NumIDs, + this function returns (in PIDList) the with processor that owns the GID for this map and returns the + local index (in LIDList) of the GID on that processor. Finally it returns the element sizes in + SizeList. + */ + int RemoteIDList(int NumIDs, const int * GIDList, int * PIDList, int * LIDList, int * SizeList) const; + + //! Returns local ID of global ID, return -1 if not found on this processor. + int LID(int GID) const; + + //! Returns global ID of local ID, return IndexBase-1 if not found on this processor. + int GID(int LID) const; + + //! Returns the LID of the element that contains the given local PointID, and the Offset of the point in that element. + int FindLocalElementID(int PointID, int & ElementID, int & ElementOffset) const; + + //! Returns true if the GID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyGID(int GID) const {return(LID(GID)!=-1);}; + + //! Returns true if the LID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyLID(int LID) const {return(GID(LID)!=BlockMapData_->IndexBase_-1);}; + + //!Returns the minimum global ID across the entire map. + int MinAllGID() const {return(BlockMapData_->MinAllGID_);}; + + //! Returns the maximum global ID across the entire map. + int MaxAllGID() const {return(BlockMapData_->MaxAllGID_);}; + + //! Returns the maximum global ID owned by this processor. + int MinMyGID() const {return(BlockMapData_->MinMyGID_);}; + + //! Returns the maximum global ID owned by this processor. + int MaxMyGID() const {return(BlockMapData_->MaxMyGID_);}; + + //! The minimum local index value on the calling processor. + int MinLID() const {return(BlockMapData_->MinLID_);}; + + //! The maximum local index value on the calling processor. + int MaxLID() const {return(BlockMapData_->MaxLID_);}; + //@} + + //! @name Size and dimension accessor functions + //@{ + //! Number of elements across all processors. + int NumGlobalElements() const {return(BlockMapData_->NumGlobalElements_);}; + + //! Number of elements on the calling processor. + int NumMyElements() const {return(BlockMapData_->NumMyElements_);}; + + //! Puts list of global elements on this processor into the user-provided array. + int MyGlobalElements(int * MyGlobalElementList) const; + + //! Returns the size of elements in the map; only valid if map has constant element size. + int ElementSize() const {return(BlockMapData_->ElementSize_);}; + + //! Size of element for specified LID. + int ElementSize(int LID) const; + + //! Returns the requested entry in the FirstPointInElementList; see FirstPointInElementList() for details. + /*! This function provides similar functionality to FirstPointInElementList(), but for simple maps may avoid + the explicit construction of the FirstPointInElementList array. Returns -1 if LID is out-of-range. + */ + int FirstPointInElement(int LID) const; + + //! Index base for this map. + int IndexBase() const {return(BlockMapData_->IndexBase_);}; + + //! Number of global points for this map; equals the sum of all element sizes across all processors. + int NumGlobalPoints() const {return(BlockMapData_->NumGlobalPoints_);}; + + //! Number of local points for this map; equals the sum of all element sizes on the calling processor. + int NumMyPoints() const {return(BlockMapData_->NumMyPoints_);}; + + //! Minimum element size on the calling processor. + int MinMyElementSize() const {return(BlockMapData_->MinMyElementSize_);}; + + //! Maximum element size on the calling processor. + int MaxMyElementSize() const {return(BlockMapData_->MaxMyElementSize_);}; + + //! Minimum element size across all processors. + int MinElementSize() const {return(BlockMapData_->MinElementSize_);}; + + //! Maximum element size across all processors. + int MaxElementSize() const {return(BlockMapData_->MaxElementSize_);}; + //@} + + //! @name Miscellaneous boolean tests + //@{ + //! Returns true if map GIDs are 1-to-1. + /*! Certain operations involving Epetra_BlockMap and Epetra_Map objects are well-defined only if + the map GIDs are uniquely present in the map. In other words, if a GID occurs in the map, it occurs + only once on a single processor and nowhere else. This boolean test returns true if this property + is true, otherwise it returns false. + */ + bool UniqueGIDs() const {return(IsOneToOne());}; + + //! Returns true if map has constant element size. + bool ConstantElementSize() const {return(BlockMapData_->ConstantElementSize_);}; + + //! Returns true if \e this and Map are identical maps + bool SameAs(const Epetra_BlockMap & Map) const; + + //! Returns true if \e this and Map have identical point-wise structure + /*! If both maps have the same number of global points and the same point + distribution across processors then this method returns true. + */ + bool PointSameAs(const Epetra_BlockMap & Map) const; + + //! Returns true if the global ID space is contiguously divided (but not necessarily uniformly) across all processors. + bool LinearMap() const {return(BlockMapData_->LinearMap_);}; + + //! Returns true if map is defined across more than one processor. + bool DistributedGlobal() const {return(BlockMapData_->DistributedGlobal_);}; + //@} + + //! @name Array accessor functions + //@{ + + //! Pointer to internal array containing list of global IDs assigned to the calling processor. + int * MyGlobalElements() const; + + //! Pointer to internal array containing a mapping between the local elements and the first local point number in each element. + /*! This array is a scan sum of the ElementSizeList such that the ith entry in FirstPointInElementList is the sum of the first + i-1 entries of ElementSizeList(). + */ + int * FirstPointInElementList() const; + + //! List of the element sizes corresponding to the array MyGlobalElements(). + int * ElementSizeList() const; + + //! For each local point, indicates the local element ID that the point belongs to. + int * PointToElementList() const; + + //! Same as ElementSizeList() except it fills the user array that is passed in. + int ElementSizeList(int * ElementSizeList)const; + + //! Same as FirstPointInElementList() except it fills the user array that is passed in. + int FirstPointInElementList(int * FirstPointInElementList)const; + + //! Same as PointToElementList() except it fills the user array that is passed in. + int PointToElementList(int * PointToElementList) const; + + //@} + + //! @name Miscellaneous + //@{ + + //! Print object to an output stream + virtual void Print(ostream & os) const; + + //! Access function for Epetra_Comm communicator. + const Epetra_Comm & Comm() const {return(*BlockMapData_->Comm_);} + + bool IsOneToOne() const {return(BlockMapData_->OneToOne_);} + + //! Assignment Operator + Epetra_BlockMap & operator=(const Epetra_BlockMap & map); + + //@} + + //! @name Expert Users and Developers Only + //@{ + + //! Returns the reference count of BlockMapData. + /*! (Intended for testing purposes.) */ + int ReferenceCount() const {return(BlockMapData_->ReferenceCount());} + + //! Returns a pointer to the BlockMapData instance this BlockMap uses. + /*! (Intended for developer use only for testing purposes.) */ + const Epetra_BlockMapData * DataPtr() const {return(BlockMapData_);} + + //@} + + private: // These need to be accessible to derived map classes. + + void GlobalToLocalSetup(); + bool DetermineIsOneToOne(); + bool IsDistributedGlobal(int NumGlobalElements, int NumMyElements) const; + void CheckValidNGE(int NumGlobalElements); + void EndOfConstructorOps(); + void CleanupData(); + + Epetra_BlockMapData * BlockMapData_; + +}; + +#endif /* EPETRA_BLOCKMAP_H */ diff --git a/fastlib/trilinos/include/Epetra_BlockMapData.h b/fastlib/trilinos/include/Epetra_BlockMapData.h new file mode 100644 index 0000000000..2caaf5dca7 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_BlockMapData.h @@ -0,0 +1,105 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_BLOCKMAPDATA_H +#define EPETRA_BLOCKMAPDATA_H + +#include "Epetra_Data.h" +#include "Epetra_IntSerialDenseVector.h" + +class Epetra_Comm; +class Epetra_Directory; +class Epetra_HashTable; + +//! Epetra_BlockMapData: The Epetra BlockMap Data Class. +/*! The Epetra_BlockMapData class is an implementation detail of Epetra_BlockMap. + It is reference-counted, and can be shared by multiple Epetra_BlockMap instances. + It derives from Epetra_Data, and inherits reference-counting from it. +*/ + +class Epetra_BlockMapData : public Epetra_Data { + friend class Epetra_BlockMap; + + private: + + //! @name Constructor/Destructor Methods + //@{ + + //! Epetra_BlockMapData Default Constructor. + Epetra_BlockMapData(int NumGlobalElements, int ElementSize, int IndexBase, const Epetra_Comm & Comm); + + //! Epetra_BlockMapData Destructor. + ~Epetra_BlockMapData(); + + //@} + + const Epetra_Comm * Comm_; + + Epetra_Directory* Directory_; + + Epetra_IntSerialDenseVector LID_; + Epetra_IntSerialDenseVector MyGlobalElements_; + Epetra_IntSerialDenseVector FirstPointInElementList_; + Epetra_IntSerialDenseVector ElementSizeList_; + Epetra_IntSerialDenseVector PointToElementList_; + + int NumGlobalElements_; + int NumMyElements_; + int IndexBase_; + int ElementSize_; + int MinMyElementSize_; + int MaxMyElementSize_; + int MinElementSize_; + int MaxElementSize_; + int MinAllGID_; + int MaxAllGID_; + int MinMyGID_; + int MaxMyGID_; + int MinLID_; + int MaxLID_; + int NumGlobalPoints_; + int NumMyPoints_; + + bool ConstantElementSize_; + bool LinearMap_; + bool DistributedGlobal_; + bool OneToOne_; + + int LastContiguousGID_; + int LastContiguousGIDLoc_; + Epetra_HashTable * LIDHash_; + + // these are intentionally declared but not defined. See Epetra Developer's Guide for details. + Epetra_BlockMapData(const Epetra_BlockMapData & BlockMapData); + Epetra_BlockMapData& operator=(const Epetra_BlockMapData & BlockMapData); + +}; +#endif /* EPETRA_BLOCKMAPDATA_H */ diff --git a/fastlib/trilinos/include/Epetra_CombineMode.h b/fastlib/trilinos/include/Epetra_CombineMode.h new file mode 100644 index 0000000000..0430041fd8 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_CombineMode.h @@ -0,0 +1,70 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_COMBINEMODE_H +#define EPETRA_COMBINEMODE_H +/*! \file Epetra_CombineMode.h + \brief Epetra_Combine Mode enumerable type + */ + +/*! \enum Epetra_CombineMode + If set to Add, components on the receiving processor will be added + together. If set to Zero, off-processor components will be ignored. + If set to Insert, off-processor components will replace existing + components on the receiving processor. If set to InsertAdd, off-processor components + will replace existing components, but multiple off-processor contributions will be added. + If set to Average, off-processor components will be averaged with + existing components on the receiving processor. (Recursive Binary Average) + If set to AbsMax, magnitudes of off-processor components will be maxed + with magnitudes of existing components of the receiving processor. + { V = Supported by Epetra_Vector and Epetra_MultiVector, + M = Supported by Epetra_CrsMatrix and Epetra_VbrMatrix } +*/ + +enum Epetra_CombineMode {Add, /*!< Components on the receiving processor + will be added together. (V,M) */ + Zero, /*!< Off-processor components will be + ignored. (V,M) */ + Insert, /*!< Off-processor components will + be inserted into locations on + receiving processor replacing existing values. (V,M) */ + InsertAdd, /*!< Off-processor components will + be inserted into locations on + receiving processor replacing existing values. (V,M) */ + Average,/*!< Off-processor components will be + averaged with existing components + on the receiving processor. (V) */ + AbsMax /*!< Magnitudes of Off-processor components will be + maxed with magnitudes of existing components + on the receiving processor. (V) */ + }; + +#endif // EPETRA_COMBINEMODE_H diff --git a/fastlib/trilinos/include/Epetra_Comm.h b/fastlib/trilinos/include/Epetra_Comm.h new file mode 100644 index 0000000000..579bc7ca71 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Comm.h @@ -0,0 +1,366 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_COMM_H +#define EPETRA_COMM_H + +#include "Epetra_Object.h" + +class Epetra_Distributor; +class Epetra_Directory; +class Epetra_BlockMap; + +//! Epetra_Comm: The Epetra Communication Abstract Base Class. +/*! The Epetra_Comm class is an interface that encapsulates the general + information and services needed for other Epetra classes to run on a + parallel computer. An Epetra_Comm object is required for building all + Epetra Map objects, which in turn are required for all other Epetra + classes. + + Epetra_Comm has default implementations, via Epetra_SerialComm and + Epetra_MpiComm, for both serial execution and MPI distributed memory + execution. It is meant to insulate the user from the specifics of + communication that are not required for normal manipulation of linear + algebra objects. Most Epetra_Comm interfaces are similar to MPI + interfaces, except that the type of data is not required as an argument + since C++ can bind to the appropriate interface based on argument typing. + + Any implementation of the Epetra_Comm interface is also responsible for + generating an Epetra_Distributor and Epetra_Directory object. +*/ + +class Epetra_Comm { + + public: + //! @name Constructor / Destructor + //@{ + //! Epetra_Comm clone constructor. + /*! The clone function will return a new heap-allocated Comm instance. + It is the responsibility of the caller to ensure that this new instance + is properly destroyed. + */ + virtual Epetra_Comm * Clone() const = 0; + //! Epetra_Comm Destructor. + virtual ~Epetra_Comm() {}; + //@} + + //! @name Barrier Methods + //@{ + //! Epetra_Comm Barrier function. + /*! Each processor must wait at the point the barrier is called until all processors have arrived. + */ + virtual void Barrier() const = 0; + //@} + + //! @name Broadcast Methods + //@{ + //! Epetra_Comm Broadcast function. + /*! Take list of input values from the root processor and sends to all other processors. + \param MyVals InOut + On entry, the root processor contains the list of values. On exit, + all processors will have the same list of values. Note that values must be + allocated on all processor before the broadcast. + \param Count In + On entry, contains the length of the list of Values. + \param Root In + On entry, contains the processor from which all processors will receive a copy of Values. + */ + + virtual int Broadcast(double * MyVals, int Count, int Root) const = 0; + + //! Epetra_Comm Broadcast function. + /*! Take list of input values from the root processor and sends to all other processors. + \param MyVals InOut + On entry, the root processor contains the list of values. On exit, + all processors will have the same list of values. Note that values must be + allocated on all processor before the broadcast. + \param Count In + On entry, contains the length of the list of Values. + \param Root In + On entry, contains the processor from which all processors will receive a copy of Values. + */ + + virtual int Broadcast(int * MyVals, int Count, int Root) const = 0; + + //! Epetra_Comm Broadcast function. + /*! Take list of input values from the root processor and sends to all other processors. + \param MyVals InOut + On entry, the root processor contains the list of values. On exit, + all processors will have the same list of values. Note that values must be + allocated on all processor before the broadcast. + \param Count In + On entry, contains the length of the list of Values. + \param Root In + On entry, contains the processor from which all processors will receive a copy of Values. + */ + + virtual int Broadcast(long * MyVals, int Count, int Root) const = 0; + //@} + + //! @name Gather Methods + //@{ + //! Epetra_Comm All Gather function. + /*! Take list of input values from all processors in the communicator and creates an ordered contiguous list of + those values on each processor. + \param MyVals In + On entry, contains the list of values to be sent to all processors. + \param AllVals Out + On exit, contains the list of values from all processors. Must be of size NumProc*Count. + \param Count In + On entry, contains the length of the list of MyVals. + */ + + virtual int GatherAll(double * MyVals, double * AllVals, int Count) const = 0; + + //! Epetra_Comm All Gather function. + /*! Take list of input values from all processors in the communicator and creates an ordered contiguous list of + those values on each processor. + \param MyVals In + On entry, contains the list of values to be sent to all processors. + \param AllVals Out + On exit, contains the list of values from all processors. Must be of size NumProc*Count. + \param Count In + On entry, contains the length of the list of MyVals. + */ + + virtual int GatherAll(int * MyVals, int * AllVals, int Count) const = 0; + + //! Epetra_Comm All Gather function. + /*! Take list of input values from all processors in the communicator and creates an ordered contiguous list of + those values on each processor. + \param MyVals In + On entry, contains the list of values to be sent to all processors. + \param AllVals Out + On exit, contains the list of values from all processors. Must be of size NumProc*Count. + \param Count In + On entry, contains the length of the list of MyVals. + */ + + virtual int GatherAll(long * MyVals, long * AllVals, int Count) const = 0; + //@} + + //! @name Sum Methods + //@{ + //! Epetra_Comm Global Sum function. + /*! Take list of input values from all processors in the communicator, computes the sum and returns the + sum to all processors. + \param PartialSums In + On entry, contains the list of values, usually partial sums computed locally, + to be summed across all processors. + \param GlobalSums Out + On exit, contains the list of values summed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + + virtual int SumAll(double * PartialSums, double * GlobalSums, int Count) const = 0; + + //! Epetra_Comm Global Sum function. + /*! Take list of input values from all processors in the communicator, computes the sum and returns the + sum to all processors. + \param PartialSums In + On entry, contains the list of values, usually partial sums computed locally, + to be summed across all processors. + \param GlobalSums Out + On exit, contains the list of values summed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int SumAll(int * PartialSums, int * GlobalSums, int Count) const = 0; + + //! Epetra_Comm Global Sum function. + /*! Take list of input values from all processors in the communicator, computes the sum and returns the + sum to all processors. + \param PartialSums In + On entry, contains the list of values, usually partial sums computed locally, + to be summed across all processors. + \param GlobalSums Out + On exit, contains the list of values summed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int SumAll(long * PartialSums, long * GlobalSums, int Count) const = 0; + //@} + + //! @name Max/Min Methods + //@{ + //! Epetra_Comm Global Max function. + /*! Take list of input values from all processors in the communicator, computes the max and returns the + max to all processors. + \param PartialMaxs In + On entry, contains the list of values, usually partial maxs computed locally; + using these Partial Maxs, the max across all processors will be computed. + \param GlobalMaxs Out + On exit, contains the list of maxs computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int MaxAll(double * PartialMaxs, double * GlobalMaxs, int Count) const = 0; + + //! Epetra_Comm Global Max function. + /*! Take list of input values from all processors in the communicator, computes the max and returns the + max to all processors. + \param PartialMaxs In + On entry, contains the list of values, usually partial maxs computed locally; + using these Partial Maxs, the max across all processors will be computed. + \param GlobalMaxs Out + On exit, contains the list of maxs computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int MaxAll(int * PartialMaxs, int * GlobalMaxs, int Count) const = 0; + + //! Epetra_Comm Global Max function. + /*! Take list of input values from all processors in the communicator, computes the max and returns the + max to all processors. + \param PartialMaxs In + On entry, contains the list of values, usually partial maxs computed locally; + using these Partial Maxs, the max across all processors will be computed. + \param GlobalMaxs Out + On exit, contains the list of maxs computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int MaxAll(long * PartialMaxs, long * GlobalMaxs, int Count) const = 0; + + //! Epetra_Comm Global Min function. + /*! Take list of input values from all processors in the communicator, computes the min and returns the + min to all processors. + \param PartialMins In + On entry, contains the list of values, usually partial mins computed locally; + using these Partial Mins, the min across all processors will be computed. + \param GlobalMins Out + On exit, contains the list of mins computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int MinAll(double * PartialMins, double * GlobalMins, int Count) const = 0; + + //! Epetra_Comm Global Min function. + /*! Take list of input values from all processors in the communicator, computes the min and returns the + min to all processors. + \param PartialMins In + On entry, contains the list of values, usually partial mins computed locally; + using these Partial Mins, the min across all processors will be computed. + \param GlobalMins Out + On exit, contains the list of mins computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int MinAll(int * PartialMins, int * GlobalMins, int Count) const = 0; + + //! Epetra_Comm Global Min function. + /*! Take list of input values from all processors in the communicator, computes the min and returns the + min to all processors. + \param PartialMins In + On entry, contains the list of values, usually partial mins computed locally; + using these Partial Mins, the min across all processors will be computed. + \param GlobalMins Out + On exit, contains the list of mins computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int MinAll(long * PartialMins, long * GlobalMins, int Count) const = 0; + //@} + + //! @name Parallel Prefix Methods + //@{ + //! Epetra_Comm Scan Sum function. + /*! Take list of input values from all processors in the communicator, computes the scan sum and returns it + to all processors such that processor i contains the sum of values from processor 0 up to and including + processor i. + \param MyVals In + On entry, contains the list of values to be summed across all processors. + \param ScanSums Out + On exit, contains the list of values summed across processors 0 through i. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int ScanSum(double * MyVals, double * ScanSums, int Count) const = 0; + + //! Epetra_Comm Scan Sum function. + /*! Take list of input values from all processors in the communicator, computes the scan sum and returns it + to all processors such that processor i contains the sum of values from processor 0 up to and including + processor i. + \param MyVals In + On entry, contains the list of values to be summed across all processors. + \param ScanSums Out + On exit, contains the list of values summed across processors 0 through i. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int ScanSum(int * MyVals, int * ScanSums, int Count) const = 0; + + //! Epetra_Comm Scan Sum function. + /*! Take list of input values from all processors in the communicator, computes the scan sum and returns it + to all processors such that processor i contains the sum of values from processor 0 up to and including + processor i. + \param MyVals In + On entry, contains the list of values to be summed across all processors. + \param ScanSums Out + On exit, contains the list of values summed across processors 0 through i. + \param Count In + On entry, contains the length of the list of values. + */ + virtual int ScanSum(long * MyVals, long * ScanSums, int Count) const = 0; + //@} + + //! @name Attribute Accessor Methods + //@{ + + //! Return my process ID. + /*! In MPI mode returns the rank of the calling process. In serial mode + returns 0. + */ + virtual int MyPID() const = 0; + + //! Returns total number of processes. + /*! In MPI mode returns the size of the MPI communicator. In serial mode + returns 1. + */ + virtual int NumProc() const = 0; + //@} + + //! @name Gather/Scatter and Directory Constructors + //@{ + //! Create a distributor object. + virtual Epetra_Distributor * CreateDistributor() const = 0; + //! Create a directory object for the given Epetra_BlockMap. + virtual Epetra_Directory * CreateDirectory(const Epetra_BlockMap & Map) const = 0; + //@} + + //! @name I/O methods + //@{ + //! Print object to an output stream + virtual void PrintInfo(ostream & os) const = 0; + //@} +}; +#endif /* EPETRA_COMM_H */ diff --git a/fastlib/trilinos/include/Epetra_CompObject.h b/fastlib/trilinos/include/Epetra_CompObject.h new file mode 100644 index 0000000000..e3136d2471 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_CompObject.h @@ -0,0 +1,111 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_COMPOBJECT_H +#define EPETRA_COMPOBJECT_H + +//! Epetra_CompObject: Functionality and data that is common to all computational classes. + +/*! The Epetra_CompObject is a base class for all Epetra computational objects. It provides the basic + mechanisms and interface specifications for floating point operations using Epetra_Flops objects. + +*/ +#include "Epetra_Object.h" +#include "Epetra_Flops.h" +//========================================================================== +class Epetra_CompObject { + + public: + + //! @name Constructors/Destructor + //@{ + //! Basic Epetra_CompObject constuctor. + Epetra_CompObject(); + + //! Epetra_CompObject copy constructor. + + Epetra_CompObject(const Epetra_CompObject& Source); + + + //! Epetra_CompObject destructor. + virtual ~Epetra_CompObject(); + //@} + + //! @name Set/Get counter method + //@{ + //! Set the internal Epetra_Flops() pointer. + void SetFlopCounter(const Epetra_Flops & FlopCounter) {FlopCounter_= (Epetra_Flops *) &FlopCounter; return;} + //! Set the internal Epetra_Flops() pointer to the flop counter of another Epetra_CompObject. + void SetFlopCounter(const Epetra_CompObject & CompObject) {FlopCounter_= (Epetra_Flops *) (CompObject.GetFlopCounter()); return;} + //! Set the internal Epetra_Flops() pointer to 0 (no flops counted). + void UnsetFlopCounter() {FlopCounter_= 0; return;} + //! Get the pointer to the Epetra_Flops() object associated with this object, returns 0 if none. + Epetra_Flops * GetFlopCounter() const {return(FlopCounter_);} + //@} + + //! @name Set flop count methods + //@{ + //! Resets the number of floating point operations to zero for \e this multi-vector. + void ResetFlops() const {if (FlopCounter_!=0) FlopCounter_->ResetFlops(); return;} + + //! Returns the number of floating point operations with \e this multi-vector. + double Flops() const {if (FlopCounter_!=0) return(FlopCounter_->Flops()); else return(0.0);} + //@} + + //! @name Update flop count methods + //@{ + //! Increment Flop count for \e this object + void UpdateFlops(int Flops) const {if (FlopCounter_!=0) FlopCounter_->UpdateFlops(Flops); return;} + + //! Increment Flop count for \e this object + void UpdateFlops(long int Flops) const {if (FlopCounter_!=0) FlopCounter_->UpdateFlops(Flops); return;} + + //! Increment Flop count for \e this object + void UpdateFlops(double Flops) const {if (FlopCounter_!=0) FlopCounter_->UpdateFlops(Flops); return;} + + //! Increment Flop count for \e this object + void UpdateFlops(float Flops) const {if (FlopCounter_!=0) FlopCounter_->UpdateFlops(Flops); return;} + //@} + + Epetra_CompObject& operator=(const Epetra_CompObject& src) + { + FlopCounter_ = src.FlopCounter_; + return(*this); + } + + protected: + + + Epetra_Flops * FlopCounter_; + +}; + +#endif /* EPETRA_COMPOBJECT_H */ diff --git a/fastlib/trilinos/include/Epetra_ConfigDefs.h b/fastlib/trilinos/include/Epetra_ConfigDefs.h new file mode 100644 index 0000000000..749e3281c8 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_ConfigDefs.h @@ -0,0 +1,297 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_CONFIGDEFS_H +#define EPETRA_CONFIGDEFS_H + +#ifndef __cplusplus +#define __cplusplus +#endif + +#define EPETRA_MAX(x,y) (( (x) > (y) ) ? x : y) /* max function */ +#define EPETRA_MIN(x,y) (( (x) < (y) ) ? x : y) /* min function */ +#define EPETRA_SGN(x) (((x) < 0.0) ? -1.0 : 1.0) /* sign function */ + +const double Epetra_MinDouble = 1.0E-100; +const double Epetra_MaxDouble = 1.0E+100; +const double Epetra_Overflow = 1.79E308; // Used to test if equilibration should be done. +const double Epetra_Underflow = 2.23E-308; + +#ifdef HAVE_CONFIG_H + +/* + * The macros PACKAGE, PACKAGE_NAME, etc, get defined for each package and need to + * be undef'd here to avoid warnings when this file is included from another package. + * KL 11/25/02 + */ +#ifdef PACKAGE +#undef PACKAGE +#endif + +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif + +#ifdef PACKAGE_BUGREPORT +#undef PACKAGE_BUGREPORT +#endif + +#ifdef PACKAGE_STRING +#undef PACKAGE_STRING +#endif + +#ifdef PACKAGE_TARNAME +#undef PACKAGE_TARNAME +#endif + +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif + +#ifdef VERSION +#undef VERSION +#endif + +#include + +#ifdef HAVE_MPI +#ifndef EPETRA_MPI +#define EPETRA_MPI +#endif +#endif + +#ifdef HAVE_CSTDLIB +#include +#endif +#ifdef HAVE_STDLIB_H +#include +#endif + +#ifdef HAVE_CSTDIO +#include +using std::sprintf; +#endif +#ifdef HAVE_STDIO_H +#include +#endif + +#ifdef HAVE_CASSERT +#include +#else +#include +#endif + +#ifdef HAVE_STRING +#include +#endif +#ifdef HAVE_STRING_H +#include +#endif + +#ifdef HAVE_IOSTREAM +#include +#else +#include +#endif + +#if HAVE_SSTREAM +#include +#endif + +#ifdef HAVE_CMATH +#include +using std::rand; +#endif +#ifdef HAVE_MATH_H +#include +#endif + +#ifdef HAVE_IOMANIP +#include +#else +#include +#endif + +#ifdef HAVE_STRING +using std::string; +#endif + +#ifdef HAVE_IOSTREAM +using std::istream; +using std::ostream; +using std::cerr; +using std::cout; +using std::endl; +using std::flush; +#endif + +/*----------------------------------------------------------------------- + Must refine the following up to #else HAVE_CONFIG_H is not defined + -----------------------------------------------------------------------*/ + +#ifdef EPETRA_SIMULATE_BOOL +#ifdef bool +#undef bool +#endif +#ifdef true +#undef true +#endif +#ifdef false +#undef false +#endif + +#define bool int +#define true 1 +#define false 0 + +#endif + +#ifndef HAVE_FORMAT_IO +const bool Epetra_FormatStdout = false; // Set true if the ostream << operator should format output +#else +const bool Epetra_FormatStdout = true; +#endif + +// Define DefultTracebackMode (HAVE_WARNING_MESSAGES and HAVE_FATAL_MESSAGES can be defined +// via the configure script command line) + +#ifdef HAVE_WARNING_MESSAGES +const int DefaultTracebackMode = 2; +#elif defined HAVE_FATAL_MESSAGES +const int DefaultTracebackMode = 1; +#else +const int DefaultTracebackMode = 0; +#endif + +#else /*HAVE_CONFIG_H is not defined*/ + +#ifndef __cplusplus +#define __cplusplus +#endif + +#if defined(SGI) || defined(SGI64) || defined(SGI32) || defined(CPLANT) + +#include +#include +#include +#include +#include +#include + +using std::string; +using std::istream; +using std::ostream; +using std::cerr; +using std::cout; +using std::endl; +using std::flush; + +#else + +#include +#include +#include +#include +#include +#include + +using std::string; +using std::istream; +using std::ostream; +using std::cerr; +using std::cout; +using std::endl; +using std::flush; + +#endif + + + +#ifdef EPETRA_SIMULATE_BOOL +#ifdef bool +#undef bool +#endif +#ifdef true +#undef true +#endif +#ifdef false +#undef false +#endif + +#define bool int +#define true 1 +#define false 0 + +#endif + +const bool Epetra_FormatStdout = true; // Set true if the ostream << operator should format output +const int DefaultTracebackMode = 1; + +#endif /*HAVE_CONFIG_H*/ + +// Delete any previous definition of EPETRA_NO_ERROR_REPORTS + +#ifdef EPETRA_CHK_ERR +#undef EPETRA_CHK_ERR +#endif +#ifdef EPETRA_CHK_PTR +#undef EPETRA_CHK_PTR +#endif +#ifdef EPETRA_CHK_REF +#undef EPETRA_CHK_REF +#endif + +// Great little macro obtained from Alan Williams (modified for dynamic switching on/off) + +#define EPETRA_CHK_ERR(a) { { int epetra_err = a; \ + if ((epetra_err < 0 && Epetra_Object::GetTracebackMode() > 0) || \ + (epetra_err > 0 && Epetra_Object::GetTracebackMode() > 1)) { \ + Epetra_Object::GetTracebackStream() << "Epetra ERROR " << epetra_err << ", " \ + << __FILE__ << ", line " << __LINE__ << endl; }\ + if (epetra_err != 0) return(epetra_err); }\ + } + +// Extension of same macro for pointer, returns zero if bad + +#define EPETRA_CHK_PTR(a) { if (a == 0 && Epetra_Object::GetTracebackMode() > 0) { \ + Epetra_Object::GetTracebackStream() << "Epetra returning zero pointer " << ", " \ + << __FILE__ << ", line " << __LINE__ << endl; } \ + return(a); \ + } +// Extension of same macro for reference, returns a default reference + +#define EPETRA_CHK_REF(a) { if (Epetra_Object::GetTracebackMode() > 0) {\ + Epetra_Object::GetTracebackStream() << "Epetra returning default reference " << ", " \ + << __FILE__ << ", line " << __LINE__ << endl; } \ + return(a); \ + } + +#endif /* EPETRA_CONFIGDEFS_H */ diff --git a/fastlib/trilinos/include/Epetra_CrsGraph.h b/fastlib/trilinos/include/Epetra_CrsGraph.h new file mode 100644 index 0000000000..7a8f3a8aab --- /dev/null +++ b/fastlib/trilinos/include/Epetra_CrsGraph.h @@ -0,0 +1,971 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_CRSGRAPH_H +#define EPETRA_CRSGRAPH_H + +#include "Epetra_DistObject.h" +#include "Epetra_CrsGraphData.h" +class Epetra_BlockMap; +class Epetra_Util; +class Epetra_Time; +class Epetra_Import; +class Epetra_Export; +class Epetra_Distributor; +class Epetra_RowMatrix; + +//! Epetra_CrsGraph: A class for constructing and using sparse compressed row graphs. + +/*! Epetra_CrsGraph enables the piecewise construction and use of sparse matrix graphs (the integer structure without + values) where entries are intended for row access. + + Epetra_CrsGraph is an attribute of all Epetra row-based matrix classes, defining their nonzero structure and also + holding their Epetra_Map attributes. + +Constructing Epetra_CrsGraph objects + +Constructing Epetra_CrsGraph objects is a multi-step process. The basic steps are as follows: +
      +
    1. Create Epetra_CrsGraph instance, including some initial storage, via constructor. In + addition to the copy constructor, Epetra_CrsGraph has four different constructors. All four of these + constructors have + an argument, StaticProfile, which by default is set to false. If it is set to true, then the + profile (the number of indices per row as defined by NumIndicesPerRow) will be rigidly enforced. + Although this takes away flexibility, it allows a single array to be allocated for all indices. + This decreases memory fragmentation and improves performance across many operations. A more detailed + discussion of the StaticProfile option is found below. +
        +
      1. User-provided row map, variable nonzero profile: This constructor is used to define the + row distribution of the graph and specify a varying number of nonzero entries per row. + It is best to use this constructor when the user will be inserting entries using global index + values and wants every column index to be included in the graph. Note that in this case, the + column map will be built for the user when FillComplete() is called. This constructor is also + appropriate for when there is a large variation in the number of indices per row. If this is not + the case, the next constructor may be more convenient to use. +
      2. User-provided row map, fixed nonzero profile: This constructor is used to define the + row distribution of the graph and specify a fixed number of nonzero entries per row. + It is best to use this constructor when the user will be inserting entries using global index + values and wants every column index to be included in the graph. Note that in this case, the + column map will be built for the user when FillComplete() is called. This constructor is also + appropriate for when there is little or no variation in the number of indices per row. +
      3. User-provided row map, user-provided column map and variable nonzero profile: + This constructor is used to define the + row \e and \e column distribution of the graph, and specify a varying number of nonzero entries per row. + It is best to use this constructor when the user will be inserting entries and already knows which columns + of the matrix should be included on each processor. Note that in this case, the + column map will \e not be built for the user when FillComplete() is called. Also, if the user attempts to + insert a column index whose GID is not part of the column map on that process, the index will be + discarded. This property can be used to "filter out" column entries that should be ignored. + This constructor is also + appropriate for when there is a large variation in the number of indices per row. If this is not + the case, the next constructor may be more convenient to use. +
      4. User-provided row map, user-provided column map and fixed nonzero profile: + This constructor is used to define the + row \e and \e column distribution of the graph, and specify a fixed number of nonzero entries per row. + It is best to use this constructor when the user will be inserting entries and already knows which columns + of the matrix should be included on each processor. Note that in this case, the + column map will \e not be built for the user when FillComplete() is called. Also, if the user attempts to + insert a column index whose GID is not part of the column map on that process, the index will be + discarded. This constructor is also + appropriate for when there is little or no variation in the number of indices per row. +
      +
    2. Enter row and column entry information via calls to the InsertGlobalIndices method. +
    3. Complete construction via FillComplete call, which performs the following tasks: +
        +
      1. Transforms indices to local index space (after this, IndicesAreLocal()==true) +
      2. Sorts column-indices within each row +
      3. Compresses out any redundant indices within rows +
      4. Computes global data such as num-nonzeros, maximum row-lengths, etc. +
      +
    4. (Optional) Optimize the graph storage via a call to OptimizeStorage. +
    + + Performance Enhancement Issues + +The Epetra_CrsGraph class attempts to address four basic types of situations, depending on the user's primary concern: + +
      +
    1. Simple, flexible construction over minimal memory use or control of column indices: In this case the user wants to provide only a row distribution + of the graph and insert indices without worrying about memory allocation performance. This type of user is best + served by the constructor that requires only a row map, and a fixed number of indices per row. In fact, setting NumIndicesPerRow=0 + is probably the best option. +
    2. Stronger control over memory allocation performance and use over flexibility and simplicity: In this case the user explicitly set + StaticProfile to true and will provide values, either a single global int or an array of int's, for NumIndicesPerRow, such that + the actual number of indices submitted to the graph will not exceed the estimates. Because we know that NumIndicesPerRow will not + be exceeded, we can pre-allocate all of the storage for the graph as a single array. This is typically much more efficient. +
    3. Explicit control over column indices: In this case the user prescribes the column map. Given the column map, any index that is + submitted for entry into the graph will be included \e only if they are present in the list of GIDs for the column map on the + processor that submits the index. This feature allows the user to define a filter such that only certain columns will be kept. The + user also prescribes the local ordering via this technique, since the ordering of GIDs in the column map imposes the local + ordering. +
    4. Construction using local indices only: In some situations, users may want to build a graph using local index values only. In this + case, the user must explicitly assign GIDs. This is done by prescribing the column map, in the same way as the previous situation. +
    + +Notes: +
      +
    • In all but the most advanced uses, users will typically \e not specify the column map. In other words, graph entries will be submitted using +GIDs not LIDs and all entries that are submitted are intended to be inserted into the graph. + +
    • If a user is not particularly worried about performance, or really needs the flexibility associated with the first situation, then there +is no need to explicitly manage the NumIndicesPerRow values or set StaticProfile to true. In this case, it is best to set NumIndicesPerRow to +zero. + +
    • Users who are concerned about performance should carefully manage NumIndicesPerRow and set StaticProfile to true. This will give the best +performance and use the least amount of memory. + +
    • A compromise approach would be to not set StaticProfile to true, giving the user flexibility, but then calling OptimizeStorage() once FillComplete() +has been called. This approach requires additional temporary memory because the graph will be copied into an efficient data structure and the old +memory deleted. However, once the copy has been made, the resulting data structure is as efficient as when StaticProfile is used. +
    + +Epetra_Map attributes + +Epetra_CrsGraph objects have four Epetra_Map attributes. + +The Epetra_Map attributes can be obtained via these accessor methods: +
      +
    • RowMap() Describes the numbering and distribution of the rows of the graph. The row-map exists and is valid + for the entire life of the graph, having been passed in as a constructor argument. The set of graph rows is defined + by the row-map and may not be changed. Rows may not be inserted or deleted by the user. The only change that may be + made is that the user can replace the row-map with a compatible row-map (which is the same except for re-numbering) + by calling the ReplaceRowMap() method. +
    • ColMap() Describes the set of column-indices that appear in the rows in each processor's portion of the graph. + Unless provided by the user at construction time, a valid column-map doesn't exist until FillComplete() is called. +
    • RangeMap() Describes the range of the matrix operator. e.g., for a matrix-vector product operation, the result + vector's map must be compatible with the range-map of the matrix operator. The range-map is usually the same as + the row-map. The range-map is set equal to the row-map at graph creation time, but may be specified by the user + when FillComplete() is called. +
    • DomainMap() Describes the domain of the matrix operator. The domain-map can be specified by the user when + FillComplete() is called. Until then, it is set equal to the row-map. +
    + +It is important to note that while the row-map and the range-map are often the same, the column-map and the domain-map +are almost never the same. The set of entries in a distributed column-map almost always form overlapping sets, with +entries being associated with more than one processor. A domain-map, on the other hand, must be a 1-to-1 map, with +entries being associated with only a single processor. + +Global versus Local indices + +After creation and before FillComplete() has been called, the column-indices of the graph are in +the global space as received from the user. One of the tasks performed by FillComplete() is to +transform the indices to a local index space. The query methods IndicesAreGlobal() and IndicesAreLocal() +return true or false depending on whether this transformation has been performed or not. + +Note the behavior of several graph methods: +
      +
    • InsertGlobalIndices() returns an error if IndicesAreLocal()==true or StorageOptimized()==true +
    • InsertMyIndices() returns an error if IndicesAreGlobal()==true or StorageOptimized()==true +
    • RemoveGlobalIndices() returns an error if IndicesAreLocal()==true or if graph was constructed in View mode +
    • RemoveMyIndices() returns an error if IndicesAreGlobal()==true or if graph was constructed in View mode +
    • ExtractGlobalRowCopy() works regardless of state of indices +
    • ExtractMyRowCopy() returns an error if IndicesAreGlobal()==true +
    • ExtractGlobalRowView() returns an error if IndicesAreLocal()==true +
    • ExtractMyRowView() returns an error if IndicesAreGlobal()==true +
    + +Note that even after a graph is constructed, it is possible to add or remove entries. However, +FillComplete must then be called again to restore the graph to a consistent state. + +*/ + +class Epetra_CrsGraph: public Epetra_DistObject { + + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_CrsGraph constuctor with variable number of indices per row. + /*! Creates a Epetra_CrsGraph object and allocates storage. + + \param CV - (In) A Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_BlockMap (or Epetra_Map or Epetra_LocalMap) listing the rows that this + processor will contribute to.In + \param NumIndicesPerRow - (In) An integer array of length NumMyRows + such that NumIndicesPerRow[i] indicates the (approximate if StaticProfile=false) number of entries in the ith row. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + */ + Epetra_CrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, const int* NumIndicesPerRow, bool StaticProfile = false); + + //! Epetra_CrsGraph constuctor with fixed number of indices per row. + /*! Creates a Epetra_CrsGraph object and allocates storage. + + \param CV - (In) A Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_BlockMap (or Epetra_Map or Epetra_LocalMap) listing the rows that this + processor will contribute to. + \param NumIndicesPerRow - (In) An integer that indicates the (approximate if StaticProfile=false) number of entries in the each row. + Note that it is possible to use 0 for this value and let fill occur during the insertion phase. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + + */ + Epetra_CrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, int NumIndicesPerRow, bool StaticProfile = false); + + //! Epetra_CrsGraph constuctor with variable number of indices per row. + /*! Creates a Epetra_CrsGraph object and allocates storage. + + \param CV - (In) A Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_BlockMap (or Epetra_Map or Epetra_LocalMap) listing the rows that this + processor will contribute to. + \param ColMap - (In) An Epetra_BlockMap (or Epetra_Map or Epetra_LocalMap) listing the columns that this + processor will contribute to. + \param NumIndicesPerRow - (In) An integer array of length NumMyRows + such that NumIndicesPerRow[i] indicates the (approximate if StaticProfile=false) number of entries in the ith row. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + */ + Epetra_CrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, + const Epetra_BlockMap& ColMap, const int* NumIndicesPerRow, bool StaticProfile = false); + + //! Epetra_CrsGraph constuctor with fixed number of indices per row. + /*! Creates a Epetra_CrsGraph object and allocates storage. + + \param CV - (In) A Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_BlockMap (or Epetra_Map or Epetra_LocalMap) listing the rows that this + processor will contribute to. + \param ColMap - (In) An Epetra_BlockMap (or Epetra_Map or Epetra_LocalMap) listing the columns that this + processor will contribute to. + \param In + NumIndicesPerRow - An integer that indicates the (approximate if StaticProfile=false) number of entries in the each row. + Note that it is possible to use 0 for this value and let fill occur during the insertion phase. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + + */ + Epetra_CrsGraph(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, + const Epetra_BlockMap& ColMap, int NumIndicesPerRow, bool StaticProfile = false); + + //! Copy constructor. + /*! This will create a Level 1 deep copy. This Graph will share ownership + of the CrsGraphData object with the right hand side Graph. + */ + Epetra_CrsGraph(const Epetra_CrsGraph& Graph); + + //! Epetra_CrsGraph Destructor + virtual ~Epetra_CrsGraph(); + //@} + + //! @name Insertion/Removal methods + //@{ + //! Enter a list of elements in a specified global row of the graph. + /*! + \param Row - (In) Global row number of indices. + \param NumIndices - (In) Number of Indices. + \param Indices - (In) Global column indices to insert. + + \return Integer error code, set to 0 if successful. If the insertion requires + that additional memory be allocated for the row, a positive error code of 1 + is returned. If the graph is a 'View' + mode graph, then a positive warning code of 2 will be returned if the + specified row already exists. Returns 1 if underlying graph data is shared + by multiple graph instances. + + \pre IndicesAreGlobal()==true, StorageOptimized()==false + */ + int InsertGlobalIndices(int GlobalRow, int NumIndices, int* Indices); + + //! Remove a list of elements from a specified global row of the graph. + /*! + \param Row - (In) Global row number of indices. + \param NumIndices - (In) Number of Indices. + \param Indices - (In) Global column indices to remove. + + \return Integer error code, set to 0 if successful. Returns 1 if data is shared. + + \pre IndicesAreGlobal()==true, StorageOptimized()==false + */ + int RemoveGlobalIndices(int GlobalRow, int NumIndices, int* Indices); + + //! Remove all indices from a specified global row of the graph. + /*! + \param Row - (In) Global row number of indices. + + \return Integer error code, set to 0 if successful. Returns 1 if data is shared. + + \pre IndicesAreGlobal()==true, StorageOptimized()==false + */ + int RemoveGlobalIndices(int Row); + + + //! Enter a list of elements in a specified local row of the graph. + /*! + \param Row - (In) Local row number of indices. + \param NumIndices - (In) Number of Indices. + \param Indices - (In) Local column indices to insert. + + \return Integer error code, set to 0 if successful. If the insertion requires + that additional memory be allocated for the row, a positive error code of 1 + is returned. If one or more of the indices is ignored (due to not being + contained in the column-map), then a positive warning code of 2 is returned. + If the graph is a 'View' mode graph, then a positive warning code of 3 will + be returned if the specified row already exists. Returns 1 if underlying + graph data is shared by multiple graph instances. + + \pre IndicesAreLocal()==true, StorageOptimized()==false + */ + int InsertMyIndices(int LocalRow, int NumIndices, int* Indices); + + //! Remove a list of elements from a specified local row of the graph. + /*! + \param Row - (In) Local row number of indices. + \param NumIndices - (In) Number of Indices. + \param Indices - (In) Local column indices to remove. + + \return Integer error code, set to 0 if successful. Returns 1 if data is shared. + + \pre IndicesAreLocal()==true, StorageOptimized()==false + */ + int RemoveMyIndices(int LocalRow, int NumIndices, int* Indices); + + //! Remove all indices from a specified local row of the graph. + /*! + \param Row - (In) Local row number of indices. + + \return Integer error code, set to 0 if successful. Returns 1 if data is shared. + + \pre IndicesAreLocal()==true, StorageOptimized()==false + */ + int RemoveMyIndices(int Row); + //@} + + //! @name Transformation methods + //@{ + + //! Tranform to local index space. Perform other operations to allow optimal matrix operations. + /*! This overloading of the FillComplete method assumes that the domain-map and range-map both equal + the row-map, and simply calls FillComplete(RowMap(), RowMap()). + \return Integer error code, set to 0 if successful. Returns 1 if data is shared (i.e., if the underlying graph-data + object has a reference-count greater than 1). + + \post IndicesAreLocal()==true, Filled()==true + */ + int FillComplete(); + + //! Transform to local index space using specified Domain/Range maps. Perform other operations to allow optimal matrix operations. + /*! Performs this sequence of operations: +
      +
    1. Transform indices to local index space +
    2. Sort column-indices within each row +
    3. Compress out any redundant indices within rows +
    4. Compute global data such as num-nonzeros, maximum row-lengths, etc. +
    + \return Integer error code, set to 0 if successful. Returns 1 if data is shared (i.e., if the underlying graph-data + object has a reference-count greater than 1). + + \post IndicesAreLocal()==true, Filled()==true + */ + int FillComplete(const Epetra_BlockMap& DomainMap, const Epetra_BlockMap& RangeMap); + + //! Make consecutive row index sections contiguous, minimize internal storage used for constructing graph. + /*! After construction and during initialization (when indices are being added via InsertGlobalIndices() etc.), the column- + indices for each row are held in a separate piece of allocated memory. This method moves the column-indices for all rows + into one large contiguous array and eliminates internal storage that is not needed after graph construction. Calling this + method can have a significant impact on memory costs and machine performance. + + If this object was constructed in View mode then this method can't make non-contiguous indices contiguous and will + return a warning code of 1 if the viewed data isn't already contiguous. + \return Integer error code, set to 0 if successful. + + \pre Filled()==true. + \pre If CV=View when the graph was constructed, then this method will be effective \only if the indices of the graph were already contiguous. In this case, the indices are left untouched and internal storage for the graph is minimized. + + \post StorageOptimized()==true, if successful + */ + int OptimizeStorage(); + + //@} + + //! @name Extraction methods + //@{ + + //! Extract a list of elements in a specified global row of the graph. Put into storage allocated by calling routine. + /*! + \param Row - (In) Global row number to get indices. + \param LenOfIndices - (In) Length of Indices array. + \param NumIndices - (Out) Number of Indices. + \param Indices - (Out) Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int ExtractGlobalRowCopy(int GlobalRow, int LenOfIndices, int& NumIndices, int* Indices) const; + + //! Extract a list of elements in a specified local row of the graph. Put into storage allocated by calling routine. + /*! + \param Row - (In) Local row number to get indices. + \param LenOfIndices - (In) Length of Indices array. + \param NumIndices - (Out) Number of Indices. + \param Indices - (Out) Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + + \pre IndicesAreLocal()==true + */ + int ExtractMyRowCopy(int LocalRow, int LenOfIndices, int& NumIndices, int* Indices) const; + + //! Get a view of the elements in a specified global row of the graph. + /*! + This function requires that the graph not be completed (FillComplete() was \e not called). + \param Row - (In) Local row number to get indices. + \param NumIndices - (Out) Number of Indices. + \param Indices - (Out) Column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Returns -1 if invalid row. Returns -2 if graph is completed. + + \pre IndicesAreLocal()==false + */ + int ExtractGlobalRowView(int GlobalRow, int& NumIndices, int*& Indices) const; + + //! Get a view of the elements in a specified local row of the graph. + /*! + This function requires that the graph be completed FillComplete() was called). + \param Row - (In) Local row number to get indices. + \param NumIndices - (Out) Number of Indices. + \param Indices - (Out) Column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Returns -1 if invalid row. Returns -2 if graph is not completed. + + \pre IndicesAreLocal()==true + */ + int ExtractMyRowView(int LocalRow, int& NumIndices, int*& Indices) const; + //@} + + //! @name Graph Properties Query Methods + //@{ + //! If FillComplete() has been called, this query returns true, otherwise it returns false. + bool Filled() const {return(CrsGraphData_->Filled_);} + + //! If OptimizeStorage() has been called, this query returns true, otherwise it returns false. + bool StorageOptimized() const {return(CrsGraphData_->StorageOptimized_);} + + //! If column indices are in global range, this query returns true, otherwise it returns false. + bool IndicesAreGlobal() const {return(CrsGraphData_->IndicesAreGlobal_);} + + //! If column indices are in local range, this query returns true, otherwise it returns false. + bool IndicesAreLocal() const {return(CrsGraphData_->IndicesAreLocal_);} + + //! If graph is lower triangular in local index space, this query returns true, otherwise it returns false. + /*! + \pre Filled()==true + */ + bool LowerTriangular() const {return(CrsGraphData_->LowerTriangular_);} + + //! If graph is upper triangular in local index space, this query returns true, otherwise it returns false. + /*! + \pre Filled()==true + */ + bool UpperTriangular() const {return(CrsGraphData_->UpperTriangular_);} + + //! If graph has no diagonal entries in global index space, this query returns true, otherwise it returns false. + /*! + \pre Filled()==true + */ + bool NoDiagonal() const {return(CrsGraphData_->NoDiagonal_);} + + //! Returns true of GID is owned by the calling processor, otherwise it returns false. + bool MyGlobalRow(int GID) const {return(RowMap().MyGID(GID));} + + //! Returns true if we have a well-defined ColMap, and returns false otherwise. + /*! \pre We have a well-defined ColMap if a) a ColMap was passed in at construction, + or b) the MakeColMap function has been called. (Calling either of the FillComplete functions + will result in MakeColMap being called.) + */ + bool HaveColMap() const {return(CrsGraphData_->HaveColMap_);} + //@} + + //! @name Atribute access functions + //@{ + + //! Returns the number of matrix rows on this processor. + int NumMyRows() const {return(CrsGraphData_->NumMyRows_);} + + //! Returns the number of matrix rows in global matrix. + int NumGlobalRows() const {return(CrsGraphData_->NumGlobalRows_);} + + //! Returns the number of entries in the set of column-indices that appear on this processor. + /*! The set of column-indices that appear on this processor is the union of column-indices that + appear in all local rows. The size of this set isn't available until FillComplete() has been called. + \pre Filled()==true + */ + int NumMyCols() const {return(CrsGraphData_->NumMyCols_);} + + //! Returns the number of matrix columns in global matrix. + /*! + \pre Filled()==true + */ + int NumGlobalCols() const {return(CrsGraphData_->NumGlobalCols_);} + + //! Returns the number of indices in the global graph. + /*! Note that if the graph's maps are defined such that some nonzeros + appear on more than one processor, then those nonzeros will be + counted more than once. If the user wishes to assemble a graph from + overlapping data, they can use Epetra_FECrsGraph. + \pre Filled()==true + */ + int NumGlobalNonzeros() const {return(CrsGraphData_->NumGlobalNonzeros_);} + + //! Returns the number of diagonal entries in the global graph, based on global row/column index comparisons. + /*! + \pre Filled()==true + */ + int NumGlobalDiagonals() const {return(CrsGraphData_->NumGlobalDiagonals_);} + + //! Returns the number of diagonal entries in the local graph, based on global row/column index comparisons. + /*! + \pre Filled()==true + */ + int NumMyDiagonals() const {return(CrsGraphData_->NumMyDiagonals_);} + + //! Returns the number of block matrix rows on this processor. + int NumMyBlockRows() const {return(CrsGraphData_->NumMyBlockRows_);} + + //! Returns the number of Block matrix rows in global matrix. + int NumGlobalBlockRows() const {return(CrsGraphData_->NumGlobalBlockRows_);} + + //! Returns the number of Block matrix columns on this processor. + /*! + \pre Filled()==true + */ + int NumMyBlockCols() const {return(CrsGraphData_->NumMyBlockCols_);} + + //! Returns the number of Block matrix columns in global matrix. + /*! + \pre Filled()==true + */ + int NumGlobalBlockCols() const {return(CrsGraphData_->NumGlobalBlockCols_);} + + //! Returns the number of Block diagonal entries in the local graph, based on global row/column index comparisons. + /*! + \pre Filled()==true + */ + int NumMyBlockDiagonals() const {return(CrsGraphData_->NumMyBlockDiagonals_);} + + //! Returns the number of Block diagonal entries in the global graph, based on global row/column index comparisons. + /*! + \pre Filled()==true + */ + int NumGlobalBlockDiagonals() const {return(CrsGraphData_->NumGlobalBlockDiagonals_);} + + //! Returns the number of entries in the global graph. + /*! + \pre Filled()==true + */ + int NumGlobalEntries() const {return(CrsGraphData_->NumGlobalEntries_);} + + //! Returns the number of entries on this processor. + /*! + \pre Filled()==true + */ + int NumMyEntries() const {return(CrsGraphData_->NumMyEntries_);} + //! Returns the max row dimension of block entries on the processor. + /*! + \pre Filled()==true + */ + int MaxRowDim() const {return(CrsGraphData_->MaxRowDim_);} + + //! Returns the max row dimension of block entries across all processors. + /*! + \pre Filled()==true + */ + int GlobalMaxRowDim() const {return(CrsGraphData_->GlobalMaxRowDim_);} + + //! Returns the max column dimension of block entries on the processor. + /*! + \pre Filled()==true + */ + int MaxColDim() const {return(CrsGraphData_->MaxColDim_);} + + //! Returns the max column dimension of block entries across all processors. + /*! + \pre Filled()==true + */ + int GlobalMaxColDim() const {return(CrsGraphData_->GlobalMaxColDim_);} + + //! Returns the number of indices in the local graph. + /*! + \pre Filled()==true + */ + int NumMyNonzeros() const {return(CrsGraphData_->NumMyNonzeros_);} + + //! Returns the current number of nonzero entries in specified global row on this processor. + int NumGlobalIndices(int Row) const; + + //! Returns the allocated number of nonzero entries in specified global row on this processor. + int NumAllocatedGlobalIndices(int Row) const; + + //! Returns the maximum number of nonzero entries across all rows on this processor. + /*! + \pre Filled()==true + */ + int MaxNumIndices() const {return(CrsGraphData_->MaxNumIndices_);} + + //! Returns the maximun number of nonzero entries across all rows across all processors. + /*! + \pre Filled()==true + */ + int GlobalMaxNumIndices() const {return(CrsGraphData_->GlobalMaxNumIndices_);} + + //! Returns the maximum number of nonzero points across all rows on this processor. + /*! For each entry in the graph, let i = the GRID of the entry and j = the CGID of the entry. Then + the entry size is the product of the rowmap elementsize of i and the colmap elementsize of i. + Let ki = sum of all entry sizes for the entries in the ith row. + For example, + if the ith block row had 5 block entries and the element size of each entry was 4-by-4, ki would be 80. + Then this function returns the max over all ki for all row on this processor. + + \pre Filled()==true + */ + int MaxNumNonzeros() const {return(CrsGraphData_->MaxNumNonzeros_);} + + //! Returns the maximun number of nonzero points across all rows across all processors. + /*! This function returns the max over all processor of MaxNumNonzeros(). + + \pre Filled()==true + */ + int GlobalMaxNumNonzeros() const {return(CrsGraphData_->GlobalMaxNumNonzeros_);} + + //! Returns the current number of nonzero entries in specified local row on this processor. + int NumMyIndices(int Row) const {if (Row<0 || Row >= NumMyRows()) return(0); + if (StorageOptimized()) return(CrsGraphData_->IndexOffset_[Row+1] - CrsGraphData_->IndexOffset_[Row]); + else return(CrsGraphData_->NumIndicesPerRow_[Row]);} + + //! Returns the allocated number of nonzero entries in specified local row on this processor. + int NumAllocatedMyIndices(int Row) const {if (Row<0 || Row >= NumMyRows()) return(0); + if (StorageOptimized()) return(CrsGraphData_->IndexOffset_[Row+1] - CrsGraphData_->IndexOffset_[Row]); + else return(CrsGraphData_->NumAllocatedIndicesPerRow_[Row]);} + + //! Returns the index base for row and column indices for this graph. + int IndexBase() const {return(CrsGraphData_->IndexBase_);} + + //! Returns the RowMap associated with this graph. + const Epetra_BlockMap& RowMap() const {return(Epetra_DistObject::Map());} + + /** Replaces the current RowMap with the user-specified map object, but only + if currentmap->PointSameAs(newmap) is true. This is a collective function. + Returns 0 if map is replaced, -1 if not. + + \pre RowMap().PointSameAs(newmap)==true + */ + int ReplaceRowMap(const Epetra_BlockMap& newmap); + + /** Replaces the current ColMap with the user-specified map object, but only + if currentmap->PointSameAs(newmap) is true. This is a collective function. + Returns 0 if map is replaced, -1 if not. + + \pre ColMap().PointSameAs(newmap)==true + */ + int ReplaceColMap(const Epetra_BlockMap& newmap); + + //! Returns the Column Map associated with this graph. + /*! + \pre HaveColMap()==true + */ + const Epetra_BlockMap& ColMap() const {return(CrsGraphData_->ColMap_);} + + //! Returns the DomainMap associated with this graph. + /*! + \pre Filled()==true + */ + const Epetra_BlockMap& DomainMap() const {return(CrsGraphData_->DomainMap_);} + + //! Returns the RangeMap associated with this graph. + /*! + \pre Filled()==true + */ + const Epetra_BlockMap& RangeMap() const {return(CrsGraphData_->RangeMap_);} + + //! Returns the Importer associated with this graph. + const Epetra_Import* Importer() const {return(CrsGraphData_->Importer_);} + + //! Returns the Exporter associated with this graph. + const Epetra_Export* Exporter() const {return(CrsGraphData_->Exporter_);} + + //! Returns a pointer to the Epetra_Comm communicator associated with this graph. + const Epetra_Comm& Comm() const {return(Epetra_DistObject::Comm());} + //@} + + //! @name Local/Global ID methods + //@{ + + //! Returns the local row index for given global row index, returns -1 if no local row for this global row. + int LRID(int GRID) const {return(RowMap().LID(GRID));} + + //! Returns the global row index for give local row index, returns IndexBase-1 if we don't have this local row. + int GRID(int LRID) const {return(RowMap().GID(LRID));} + + //! Returns the local column index for given global column index, returns -1 if no local column for this global column. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + int LCID(int GCID) const + { + return( CrsGraphData_->HaveColMap_ ? ColMap().LID(GCID) : -1 ); + } + + //! Returns the global column index for give local column index, returns IndexBase-1 if we don't have this local column. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + int GCID(int LCID) const + { + return( CrsGraphData_->HaveColMap_ ? ColMap().GID(LCID) : -1 ); + } + + //! Returns true if the GRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyGRID(int GRID) const {return(LRID(GRID) != -1);} + + //! Returns true if the LRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyLRID(int LRID) const {return(GRID(LRID) != IndexBase() - 1);} + + //! Returns true if the GCID passed in belongs to the calling processor in this map, otherwise returns false. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + bool MyGCID(int GCID) const {return(LCID(GCID) != -1);} + + //! Returns true if the LRID passed in belongs to the calling processor in this map, otherwise returns false. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + bool MyLCID(int LCID) const {return(GCID(LCID) != IndexBase() - 1);} + //@} + + //! @name Inlined Operator Methods + //@{ + + //! Inlined bracket operator for fast access to data. (Const and Non-const versions) + /*! No error checking and dangerous for optimization purposes. + \param Loc (In) - Local row. + + \return reference to pointer to locally indexed Loc row in matrix. + */ + + inline int* operator[]( int Loc ) { + if (StorageOptimized()){ return(CrsGraphData_->All_Indices_.Values() + CrsGraphData_->IndexOffset_[Loc]);} + else return(CrsGraphData_->Indices_[Loc]); } + + inline int* operator[]( int Loc ) const { + if (StorageOptimized()) { return(CrsGraphData_->All_Indices_.Values() +CrsGraphData_->IndexOffset_[Loc]);} + else return(CrsGraphData_->Indices_[Loc]); } + + //@} + + //! Assignment operator + /*! This will do a Level 1 deep copy. It will share ownership of the CrsGraphData + with the right hand side Graph. + */ + Epetra_CrsGraph& operator = (const Epetra_CrsGraph& Source); + + //! @name I/O Methods + //@{ + + //! Print method + virtual void Print(ostream& os) const; + + void PrintGraphData(ostream& os) const {CrsGraphData_->Print(os);} + void PrintGraphData(ostream& os, int level) const {CrsGraphData_->Print(os, level);} + //@} + + //! @name Deprecated methods: These methods still work, but will be removed in a future version + //@{ + + //! Use ColMap() instead. + const Epetra_BlockMap& ImportMap() const {return(CrsGraphData_->ColMap_);} + + //! Use FillComplete() instead. + int TransformToLocal(); + + //! Use FillComplete(const Epetra_BlockMap& DomainMap, const Epetra_BlockMap& RangeMap) instead. + int TransformToLocal(const Epetra_BlockMap* DomainMap, const Epetra_BlockMap* RangeMap); + + //@} + + //! @name Expert Users and Developers Only + //@{ + + //! Returns the reference count of CrsGraphData. + /*! (Intended for testing purposes.) */ + int ReferenceCount() const {return(CrsGraphData_->ReferenceCount());} + + //! Returns a pointer to the CrsGraphData instance this CrsGraph uses. + /*! (Intended for developer use only for testing purposes.) */ + const Epetra_CrsGraphData* DataPtr() const {return(CrsGraphData_);} + + //@} + + // functions listed in protected are the ones used by CrsMatrix and VbrMatrix. + // functions listed in private are the ones that are really private. + // (just pretend CrsMatrix and VbrMatrix derive from CrsGraph to understand the distinction.) + friend class Epetra_CrsMatrix; + friend class Epetra_VbrMatrix; + friend class Epetra_FECrsGraph; + friend class Epetra_FECrsMatrix; + friend class Epetra_FEVbrMatrix; + friend class Epetra_OffsetIndex; + + protected: + int *All_Indices() const { + if (!StorageOptimized()) throw ReportError("This method: int *All_Indices() cannot be called when StorageOptimized()==false", -1); + else return(CrsGraphData_->All_Indices_.Values());} + int *IndexOffset() const { + if (!StorageOptimized()) throw ReportError("This method: int *IndexOffset() cannot be called when StorageOptimized()==false", -1); + else return(CrsGraphData_->IndexOffset_.Values());} + int* NumIndicesPerRow() const { + if (StorageOptimized()) throw ReportError("This method: int* NumIndicesPerRow() cannot be called when StorageOptimized()==true", -1); + else return(CrsGraphData_->NumIndicesPerRow_.Values());} + int* NumAllocatedIndicesPerRow() const { + if (StorageOptimized()) throw ReportError("This method: int* NumAllocatedIndicesPerRow() cannot be called when StorageOptimized()==true", -1); + else return(CrsGraphData_->NumAllocatedIndicesPerRow_.Values());} + int** Indices() const { + if (StorageOptimized()) throw ReportError("This method: int** Indices() cannot be called when StorageOptimized()==true", -1); + else return(CrsGraphData_->Indices_);} + int* Indices(int LocalRow) const { + if (StorageOptimized()) return(CrsGraphData_->All_Indices_.Values()+CrsGraphData_->IndexOffset_[LocalRow]); + else return(CrsGraphData_->Indices_[LocalRow]);} + // If column indices are stored in one long array (via a call to OptimizeStorage), + // IndicesAreContiguous returns true, otherwise it returns false. + bool IndicesAreContiguous() const {return(CrsGraphData_->IndicesAreContiguous_);} + bool StaticProfile() const {return(CrsGraphData_->StaticProfile_);} + bool GlobalConstantsComputed() const; + bool FindGlobalIndexLoc(int LocalRow, int Index, int Start, int& Loc) const; + bool FindGlobalIndexLoc(int NumIndices, const int* Indices, int Index, int Start, int& Loc) const; + bool FindMyIndexLoc(int LocalRow, int Index, int Start, int& Loc) const; + bool FindMyIndexLoc(int NumIndices, const int* Indices, int Index, int Start, int& Loc) const; + int InsertIndices(int Row, int NumIndices, int* Indices); + int MakeIndicesLocal(const Epetra_BlockMap& DomainMap, const Epetra_BlockMap& RangeMap); + void SetIndicesAreLocal(bool Flag) {CrsGraphData_->IndicesAreLocal_ = Flag;} + void SetIndicesAreGlobal(bool Flag) {CrsGraphData_->IndicesAreGlobal_ = Flag;} + void SetSorted(bool Flag) {CrsGraphData_->Sorted_ = Flag;} + + //! Sort column indices, row-by-row, in ascending order. + /*! + \return Integer error code, set to 0 if successful. Returns 1 if data is shared. + */ + int SortIndices(); + + //! If SortIndices() has been called, this query returns true, otherwise it returns false. + bool Sorted() const {return(CrsGraphData_->Sorted_);} + + //! Removes any redundant column indices in the rows of the graph. + /*! + \return Integer error code, set to 0 if successful. Returns 1 if data is shared. + */ + int RemoveRedundantIndices(); + + //! If RemoveRedundantIndices() has been called, this query returns true, otherwise it returns false. + bool NoRedundancies() const {return(CrsGraphData_->NoRedundancies_);} + + private: + void SetGlobalConstantsComputed(bool Flag) {CrsGraphData_->GlobalConstantsComputed_ = Flag;} + void SetIndicesAreContiguous(bool Flag) {CrsGraphData_->IndicesAreContiguous_ = Flag;} + void SetNoRedundancies(bool Flag) {CrsGraphData_->NoRedundancies_ = Flag;} + void ComputeIndexState(); + int MakeColMap(const Epetra_BlockMap& DomainMap, const Epetra_BlockMap& RangeMap); + int Allocate(const int* NumIndicesPerRow, int Inc, bool StaticProfile); + //int ReAllocate(); + int ComputeGlobalConstants(); + void SetFilled(bool Flag) {CrsGraphData_->Filled_ = Flag;} + bool Allocated() const {return(CrsGraphData_->Allocated_);} + void SetAllocated(bool Flag) {CrsGraphData_->Allocated_ = Flag;} + + int CheckSizes(const Epetra_SrcDistObject& A); + + int CopyAndPermute(const Epetra_SrcDistObject& Source, + int NumSameIDs, + int NumPermuteIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + int CopyAndPermuteRowMatrix(const Epetra_RowMatrix& A, + int NumSameIDs, + int NumPermuteIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + int CopyAndPermuteCrsGraph(const Epetra_CrsGraph& A, + int NumSameIDs, + int NumPermuteIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + + int PackAndPrepare(const Epetra_SrcDistObject& Source, + int NumExportIDs, + int* ExportLIDs, + int& LenExports, + char*& Exports, + int& SizeOfPacket, + int * Sizes, + bool & VarSizes, + Epetra_Distributor& Distor); + int PackAndPrepareCrsGraph(const Epetra_CrsGraph& A, + int NumExportIDs, + int* ExportLIDs, + int& LenExports, + char*& Exports, + int& SizeOfPacket, + int* Sizes, + bool& VarSizes, + Epetra_Distributor& Distor); + int PackAndPrepareRowMatrix(const Epetra_RowMatrix& A, + int NumExportIDs, + int* ExportLIDs, + int& LenExports, + char*& Exports, + int& SizeOfPacket, + int* Sizes, + bool& VarSizes, + Epetra_Distributor& Distor); + + int UnpackAndCombine(const Epetra_SrcDistObject& Source, + int NumImportIDs, + int* ImportLIDs, + int LenImports, + char* Imports, + int& SizeOfPacket, + Epetra_Distributor& Distor, + Epetra_CombineMode CombineMode, + const Epetra_OffsetIndex * Indexor); + + void CleanupData(); + + Epetra_CrsGraphData* CrsGraphData_; + +}; +#endif /* EPETRA_CRSGRAPH_H */ diff --git a/fastlib/trilinos/include/Epetra_CrsGraphData.h b/fastlib/trilinos/include/Epetra_CrsGraphData.h new file mode 100644 index 0000000000..359dca7c04 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_CrsGraphData.h @@ -0,0 +1,156 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_CRSGRAPHDATA_H +#define EPETRA_CRSGRAPHDATA_H + +#include "Epetra_Data.h" +#include "Epetra_DataAccess.h" +#include "Epetra_BlockMap.h" +#include "Epetra_IntSerialDenseVector.h" +class Epetra_Import; +class Epetra_Export; + +//! Epetra_CrsGraphData: The Epetra CrsGraph Data Class. +/*! The Epetra_CrsGraphData class is an implementation detail of Epetra_CrsGraph. + It is reference-counted, and can be shared by multiple Epetra_CrsGraph instances. + It derives from Epetra_Data, and inherits reference-counting from it. +*/ + +class Epetra_CrsGraphData : public Epetra_Data { + friend class Epetra_CrsGraph; + + private: + + //! @name Constructor/Destructor Methods + //@{ + + //! Epetra_CrsGraphData Default Constructor. + Epetra_CrsGraphData(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, bool StaticProfile); + + //! Epetra_CrsGraphData Constructor (user provided ColMap). + Epetra_CrsGraphData(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, const Epetra_BlockMap& ColMap, bool StaticProfile); + + //! Epetra_CrsGraphData copy constructor (not defined). + Epetra_CrsGraphData(const Epetra_CrsGraphData& CrsGraphData); + + //! Epetra_CrsGraphData Destructor. + ~Epetra_CrsGraphData(); + + //@} + + //! Outputs state of almost all data members. (primarily used for testing purposes). + /*! Output level: Uses same scheme as chmod. 4-bit = BlockMaps, 2-bit = Indices, 1-bit = Everything else. + Default paramenter sets it to 3, which is everything but the BlockMaps. Commonly used options: + 1 = Everything except the BlockMaps & Indices_ + 2 = Just Indices_ + 3 = Everything except the BlockMaps + */ + void Print(ostream& os, int level = 3) const; + + //! Epetra_CrsGraphData assignment operator (not defined) + Epetra_CrsGraphData& operator=(const Epetra_CrsGraphData& CrsGraphData); + + //! @name Helper methods called in CrsGraph. Mainly memory allocations and deallocations. + //@{ + + //! called by FillComplete (and TransformToLocal) + int MakeImportExport(); + + //! called by PackAndPrepare + int ReAllocateAndCast(char*& UserPtr, int& Length, const int IntPacketSizeTimesNumTrans); + + //@} + + // Defined by CrsGraph::FillComplete and related + Epetra_BlockMap RowMap_; + Epetra_BlockMap ColMap_; + Epetra_BlockMap DomainMap_; + Epetra_BlockMap RangeMap_; + + const Epetra_Import* Importer_; + const Epetra_Export* Exporter_; + + bool HaveColMap_; + bool Filled_; + bool Allocated_; + bool Sorted_; + bool StorageOptimized_; + bool NoRedundancies_; + bool IndicesAreGlobal_; + bool IndicesAreLocal_; + bool IndicesAreContiguous_; + bool LowerTriangular_; + bool UpperTriangular_; + bool NoDiagonal_; + bool GlobalConstantsComputed_; + bool StaticProfile_; + + int IndexBase_; + + int NumGlobalEntries_; + int NumGlobalBlockRows_; + int NumGlobalBlockCols_; + int NumGlobalBlockDiagonals_; + int NumMyEntries_; + int NumMyBlockRows_; + int NumMyBlockCols_; + int NumMyBlockDiagonals_; + + int MaxRowDim_; + int MaxColDim_; + int GlobalMaxRowDim_; + int GlobalMaxColDim_; + int MaxNumNonzeros_; + int GlobalMaxNumNonzeros_; + + int NumGlobalNonzeros_; + int NumGlobalRows_; + int NumGlobalCols_; + int NumGlobalDiagonals_; + int NumMyNonzeros_; + int NumMyRows_; + int NumMyCols_; + int NumMyDiagonals_; + + int MaxNumIndices_; + int GlobalMaxNumIndices_; + + int** Indices_; + Epetra_IntSerialDenseVector NumAllocatedIndicesPerRow_; + Epetra_IntSerialDenseVector NumIndicesPerRow_; + Epetra_IntSerialDenseVector IndexOffset_; + Epetra_IntSerialDenseVector All_Indices_; + Epetra_DataAccess CV_; + +}; + +#endif /* EPETRA_CRSGRAPHDATA_H */ diff --git a/fastlib/trilinos/include/Epetra_CrsMatrix.h b/fastlib/trilinos/include/Epetra_CrsMatrix.h new file mode 100644 index 0000000000..a98e2f3d37 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_CrsMatrix.h @@ -0,0 +1,1237 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_CRSMATRIX_H +#define EPETRA_CRSMATRIX_H + +#include "Epetra_DistObject.h" +#include "Epetra_CompObject.h" +#include "Epetra_BLAS.h" +#include "Epetra_RowMatrix.h" +#include "Epetra_Operator.h" +#include "Epetra_CrsGraph.h" +class Epetra_Map; +class Epetra_Import; +class Epetra_Export; +class Epetra_Vector; +class Epetra_MultiVector; + +// Define this to see a complete dump a an Epetra_CrsMatrix::Multiply(...) call +//#define EPETRA_CRS_MATRIX_TRACE_DUMP_MULTIPLY + +#ifdef EPETRA_CRS_MATRIX_TRACE_DUMP_MULTIPLY +extern bool Epetra_CrsMatrixTraceDumpMultiply; +#endif // EPETRA_CRS_MATRIX_TRACE_DUMP_MULTIPLY + +//! Epetra_CrsMatrix: A class for constructing and using real-valued double-precision sparse compressed row matrices. + +/*! The Epetra_CrsMatrix class is a sparse compressed row matrix object. This matrix can be + used in a parallel setting, with data distribution described by Epetra_Map attributes. + The structure or graph of the matrix is defined by an Epetra_CrsGraph attribute. + + In addition to coefficient access, the primary operations provided by Epetra_CrsMatrix are matrix + times vector and matrix times multi-vector multiplication. + + Epetra_CrsMatrix matrices can be square or rectangular. + +Creating and filling Epetra_CrsMatrix objects + +Constructing Epetra_CrsMatrix objects is a multi-step process. The basic steps are as follows: +
      +
    1. Create Epetra_CrsMatrix instance, including storage, via one of the constructors: +
        +
      • Constructor that accepts one Epetra_Map object, a row-map defining the distribution of matrix rows. +
      • Constructor that accepts two Epetra_Map objects. (The second map is a column-map, and describes the set + of column-indices that appear in each processor's portion of the matrix. Generally these are + overlapping sets -- column-indices may appear on more than one processor.) +
      • Constructor that accepts an Epetra_CrsGraph object, defining the non-zero structure of the matrix. +
      + Note that the constructors which accept Epetra_Map arguments also accept an argument that gives an + estimate of the number of nonzeros per row. This allows storage to be pre-allocated and can improve + the performance of the data input methods. The estimate need not be accurate, as additional storage is + allocated automatically when needed. However, a more accurate estimate helps performance by reducing + the amount of extra memory allocation. +
    2. Enter values via one or more Insert/Replace/SumInto functions. +
    3. Complete construction by calling FillComplete. +
    + +Note that, even after a matrix is constructed (FillComplete has been called), it is possible to update existing +matrix entries. It is \e not possible to create new entries. + +Epetra_Map attributes + +Epetra_CrsMatrix objects have four Epetra_Map attributes, which are held by the Epetra_CrsGraph attribute. + +The Epetra_Map attributes can be obtained via these accessor methods: +
      +
    • RowMap() Describes the numbering and distribution of the rows of the matrix. The row-map exists and is valid + for the entire life of the matrix. The set of matrix rows is defined by the row-map and may not be changed. Rows + may not be inserted or deleted by the user. The only change that may be made is that the user can replace the + row-map with a compatible row-map (which is the same except for re-numbering) by calling the ReplaceRowMap() method. +
    • ColMap() Describes the set of column-indices that appear in the rows in each processor's portion of the matrix. + Unless provided by the user at construction time, a valid column-map doesn't exist until FillComplete() is called. +
    • RangeMap() Describes the range of the matrix operator. e.g., for a matrix-vector product operation, the result + vector's map must be compatible with the range-map of this matrix. The range-map is usually the same as the row-map. + The range-map is set equal to the row-map at matrix creation time, but may be specified by the user when + FillComplete() is called. +
    • DomainMap() Describes the domain of the matrix operator. The domain-map can be specified by the user when + FillComplete() is called. Until then, it is set equal to the row-map. +
    + +It is important to note that while the row-map and the range-map are often the same, the column-map and the domain-map +are almost never the same. The set of entries in a distributed column-map almost always form overlapping sets, with +entries being associated with more than one processor. A domain-map, on the other hand, must be a 1-to-1 map, with +entries being associated with only a single processor. + +Local versus Global Indices + +Epetra_CrsMatrix has query functions IndicesAreLocal() and IndicesAreGlobal(), which are used to determine whether the +underlying Epetra_CrsGraph attribute's column-indices have been transformed into a local index space or not. (This +transformation occurs when the method Epetra_CrsGraph::FillComplete() is called, which happens when the +method Epetra_CrsMatrix::FillComplete() is called.) The state of the indices in the +graph determines the behavior of many Epetra_CrsMatrix methods. If an Epetra_CrsMatrix instance is constructed using +one of the constructors that does not accept a pre-existing Epetra_CrsGraph object, then an Epetra_CrsGraph attribute +is created internally and its indices remain untransformed (IndicesAreGlobal()==true) until Epetra_CrsMatrix::FillComplete() +is called. The query function Epetra_CrsMatrix::Filled() returns true if Epetra_CrsMatrix::FillComplete() has been +called. + +Note the following method characteristics: + +
      +
    • InsertGlobalValues() may only be used to insert new nonzeros in the matrix if indices are global. +
    • SumIntoGlobalValues() may be used regardless of whether indices are global or local, but can only be used + to update matrix locations that already exist; it can never be used to establish new nonzero locations. +
    • ReplaceGlobalValues() may also be used only to update matrix locations that already exist, and works + regardless of whether indices are local or global. +
    • SumIntoMyValues() and ReplaceMyValues() may only be used if indices are local. +
    • Multiply() may only be used after FillComplete() has been called. +
    + +Most methods have preconditions documented, check documentation for specific methods not mentioned here. + + Counting Floating Point Operations + +Each Epetra_CrsMatrix object keeps track of the number +of \e serial floating point operations performed using the specified object as the \e this argument +to the function. The Flops() function returns this number as a double precision number. Using this +information, in conjunction with the Epetra_Time class, one can get accurate parallel performance +numbers. The ResetFlops() function resets the floating point counter. + +\warning A Epetra_Map is required for the Epetra_CrsMatrix constructor. + +*/ + +class Epetra_CrsMatrix: public Epetra_DistObject, public Epetra_CompObject, public Epetra_BLAS, public virtual Epetra_RowMatrix { + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_CrsMatrix constructor with variable number of indices per row. + /*! Creates a Epetra_CrsMatrix object and allocates storage. + + \param CV - (In) An Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_Map defining the numbering and distribution of matrix rows. + \param NumEntriesPerRow - (In) An integer array of length NumRows + such that NumEntriesPerRow[i] indicates the (approximate if StaticProfile=false) number of entries in the ith row. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + */ + Epetra_CrsMatrix(Epetra_DataAccess CV, const Epetra_Map& RowMap, const int* NumEntriesPerRow, bool StaticProfile = false); + + //! Epetra_CrsMatrix constructor with fixed number of indices per row. + /*! Creates a Epetra_CrsMatrix object and allocates storage. + + \param CV - (In) An Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_Map defining the numbering and distribution of matrix rows. + \param NumEntriesPerRow - (In) An integer that indicates the (approximate) number of entries in the each row. + Note that it is possible to use 0 for this value and let fill occur during the insertion phase. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + + */ + Epetra_CrsMatrix(Epetra_DataAccess CV, const Epetra_Map& RowMap, int NumEntriesPerRow, bool StaticProfile = false); + + //! Epetra_CrsMatrix constructor with variable number of indices per row. + /*! Creates a Epetra_CrsMatrix object and allocates storage. + + \param CV - (In) An Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_Map defining the numbering and distribution of matrix rows. + \param ColMap - (In) An Epetra_Map defining the set of column-indices that appear in each processor's + locally owned matrix rows. + \param NumEntriesPerRow - (In) An integer array of length NumRows + such that NumEntriesPerRow[i] indicates the (approximate if StaticProfile=false) number of entries in the ith row. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + */ + Epetra_CrsMatrix(Epetra_DataAccess CV, const Epetra_Map& RowMap, const Epetra_Map& ColMap, const int* NumEntriesPerRow, bool StaticProfile = false); + + //! Epetra_CrsMatrix constuctor with fixed number of indices per row. + /*! Creates a Epetra_CrsMatrix object and allocates storage. + + \param CV - (In) An Epetra_DataAccess enumerated type set to Copy or View. + \param RowMap - (In) An Epetra_Map defining the numbering and distribution of matrix rows. + \param ColMap - (In) An Epetra_Map defining the set of column-indices that appear in each processor's + locally owned matrix rows. + \param NumEntriesPerRow - (In) An integer that indicates the (approximate if StaticProfile=false) number of entries in the each row. + Note that it is possible to use 0 for this value and let fill occur during the insertion phase. + \param StaticProfile - (In) Optional argument that indicates whether or not NumIndicesPerRow should be interpreted as an exact + count of nonzeros, or should be used as an approximation. By default this value is false, allowing the profile to be determined + dynamically. If the user sets it to true, then the memory allocation for the Epetra_CrsGraph object will be done in one large + block, saving on memory fragmentation and generally improving the performance of matrix multiplication and solve kernels. + + */ + Epetra_CrsMatrix(Epetra_DataAccess CV, const Epetra_Map& RowMap, const Epetra_Map& ColMap, int NumEntriesPerRow, bool StaticProfile = false); + + //! Construct a matrix using an existing Epetra_CrsGraph object. + /*! Allows the nonzero structure from another matrix, or a structure that was + constructed independently, to be used for this matrix. + \param CV - (In) An Epetra_DataAccess enumerated type set to Copy or View. + \param Graph - (In) A Epetra_CrsGraph object, constructed directly or extracted from another Epetra matrix object. + */ + + Epetra_CrsMatrix(Epetra_DataAccess CV, const Epetra_CrsGraph& Graph); + + //! Copy constructor. + Epetra_CrsMatrix(const Epetra_CrsMatrix& Matrix); + + //! Epetra_CrsMatrix Destructor + virtual ~Epetra_CrsMatrix(); + //@} + + //! @name Insertion/Replace/SumInto methods + //@{ + + //! Assignment operator + Epetra_CrsMatrix& operator=(const Epetra_CrsMatrix& src); + + //! Initialize all values in the matrix with constant value. + /*! + \param ScalarConstant - (In) Value to use. + + \return Integer error code, set to 0 if successful. + \pre None. + \post All values in \e this set to ScalarConstant. + */ + int PutScalar(double ScalarConstant); + + //! Multiply all values in the matrix by a constant value (in place: A <- ScalarConstant * A). + /*! + \param ScalarConstant - (In) Value to use. + + \return Integer error code, set to 0 if successful. + \pre None. + \post All values of \e this have been multiplied by ScalarConstant. + */ + int Scale(double ScalarConstant); + + //! Insert a list of elements in a given global row of the matrix. + /*! + This method is used to construct a matrix for the first time. It cannot + be used if the matrix structure has already been fixed (via a call to FillComplete()). + If multiple values are inserted for the same matrix entry, the values are initially + stored separately, so memory use will grow as a result. However, when FillComplete is called + the values will be summed together and the additional memory will be released. + + For example, if the values 2.0, 3.0 and 4.0 are all inserted in Row 1, Column 2, extra storage + is used to store each of the three values separately. In this way, the insert process does not + require any searching and can be faster. However, when FillComplete() is called, the values + will be summed together to equal 9.0 and only a single entry will remain in the matrix for + Row 1, Column 2. + + \param GlobalRow - (In) Row number (in global coordinates) to put elements. + \param NumEntries - (In) Number of entries. + \param Values - (In) Values to enter. + \param Indices - (In) Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Note that if the + allocated length of the row has to be expanded, a positive warning code + will be returned. + + \warning This method may not be called once FillComplete() has been called. + + \pre IndicesAreLocal()==false && IndicesAreContiguous()==false + */ + int InsertGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices); + + //! Replace specified existing values with this list of entries for a given global row of the matrix. + /*! + \param GlobalRow - (In) Row number (in global coordinates) to put elements. + \param NumEntries - (In) Number of entries. + \param Values - (In) Values to enter. + \param Indices - (In) Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Note that if a value + is not already present for the specified location in the matrix, the + input value will be ignored and a positive warning code will be returned. + + \pre IndicesAreLocal()==false && IndicesAreContiguous()==false + */ + int ReplaceGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices); + + //! Add this list of entries to existing values for a given global row of the matrix. + /*! + \param GlobalRow - (In) Row number (in global coordinates) to put elements. + \param NumEntries - (In) Number of entries. + \param Values - (In) Values to enter. + \param Indices - (In) Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Note that if a value + is not already present for the specified location in the matrix, the + input value will be ignored and a positive warning code will be returned. + + \pre IndicesAreLocal()==false && IndicesAreContiguous()==false + */ + int SumIntoGlobalValues(int GlobalRow, int NumEntries, double* Values, int* Indices); + + //! Insert a list of elements in a given local row of the matrix. + /*! + \param MyRow - (In) Row number (in local coordinates) to put elements. + \param NumEntries - (In) Number of entries. + \param Values - (In) Values to enter. + \param Indices - (In) Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Note that if the + allocated length of the row has to be expanded, a positive warning code + will be returned. + \pre IndicesAreGlobal()==false && (IndicesAreContiguous()==false || CV_==View) + \post The given local row of the matrix has been updated as described above. + + */ + int InsertMyValues(int MyRow, int NumEntries, double* Values, int* Indices); + + //! Replace current values with this list of entries for a given local row of the matrix. + /*! + \param MyRow - (In) Row number (in local coordinates) to put elements. + \param NumEntries - (In) Number of entries. + \param Values - (In) Values to enter. + \param Indices - (In) Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Note that if a value + is not already present for the specified location in the matrix, the + input value will be ignored and a positive warning code will be returned. + \pre IndicesAreLocal()==true + \post MyRow contains the given list of Values at the given Indices. + */ + int ReplaceMyValues(int MyRow, int NumEntries, double* Values, int* Indices); + + //! Add this list of entries to existing values for a given local row of the matrix. + /*! + \param MyRow - (In) Row number (in local coordinates) to put elements. + \param NumEntries - (In) Number of entries. + \param Values - (In) Values to enter. + \param Indices - (In) Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. Note that if the + allocated length of the row has to be expanded, a positive warning code + will be returned. + \pre IndicesAreLocal()==true + \post The given Values at the given Indices have been summed into the + entries of MyRow. + */ + int SumIntoMyValues(int MyRow, int NumEntries, double* Values, int* Indices); + + //! Replaces diagonal values of the matrix with those in the user-provided vector. + /*! This routine is meant to allow replacement of {\bf existing} diagonal values. + If a diagonal value does not exist for a given row, the corresponding value in + the input Epetra_Vector will be ignored and the return code will be set to 1. + + The Epetra_Map associated with the input Epetra_Vector must be compatible with + the RowMap of the matrix. + + \param Diagonal - (In) New values to be placed in the main diagonal. + + \return Integer error code, set to 0 if successful, set to 1 on the calling processor if one or more diagonal entries not present in matrix. + \pre Filled()==true + \post Diagonal values have been replaced with the values of Diagonal. + */ + int ReplaceDiagonalValues(const Epetra_Vector& Diagonal); + + //@} + + //! @name Transformation methods + //@{ + + + //! Signal that data entry is complete. Perform transformations to local index space. + /* This version of FillComplete assumes that the domain and range + distributions are identical to the matrix row distributions. + \param OptimizeDataStorage - (In) If true, storage will be packed for optimal performance. Depending + on how the matrix was constructed, optimizing the storage may have no impact on performance + or one-time memory use, or may have a large impact. If the user was careful in allocating memory + for the matrix by setting StaticProfile to true in the matrix constructor, then no extra storage + will be allocated in attempting to optimize storage. If the user did not set StaticProfile to true, + then optimizing the storage will temporarily use additional memory, will have a noticeable impact + on performance and ultimately reduce the storage associated with the matrix. + + By default storage will be optimized. If you cannot tolerate the increased temporary memory use, + should set this value to false. + + \return error code, 0 if successful. Returns a positive warning code of 3 + if the matrix is rectangular (meaning that the other overloading of + FillComplete should have been called, with differen domain-map and + range-map specified). + */ + int FillComplete(bool OptimizeDataStorage = true); + + //! Signal that data entry is complete. Perform transformations to local index space. + /* This version of FillComplete requires the explicit specification of the domain + and range distribution maps. These maps are used for importing and exporting vector + and multi-vector elements that are needed for distributed matrix computations. For + example, to compute y = Ax in parallel, we would specify the DomainMap as the distribution + of the vector x and the RangeMap as the distribution of the vector y. + \param DomainMap - (In) Map that describes the distribution of vector and multi-vectors in the + matrix domain. + \param RangeMap - (In) Map that describes the distribution of vector and multi-vectors in the + matrix range. + + \param OptimizeDataStorage - (In) If true, storage will be packed for optimal performance. Depending + on how the matrix was constructed, optimizing the storage may have no impact on performance + or one-time memory use, or may have a large impact. If the user was careful in allocating memory + for the matrix by setting StaticProfile to true in the matrix constructor, then no extra storage + will be allocated in attempting to optimize storage. If the user did not set StaticProfile to true, + then optimizing the storage will temporarily use additional memory, will have a noticeable impact + on performance and ultimately reduce the storage associated with the matrix. + + By default storage will be optimized. If you cannot tolerate the increased temporary memory use, + should set this value to false. + + \return error code, 0 if successful. positive warning code of 2 if it is detected that the + matrix-graph got out of sync since this matrix was constructed (for instance if + graph.FillComplete() was called by another matrix that shares the graph) + + \post IndicesAreLocal()==true + */ + int FillComplete(const Epetra_Map& DomainMap, const Epetra_Map& RangeMap, bool OptimizeDataStorage = true); + + //! Make consecutive row index sections contiguous, minimize internal storage used for constructing graph. + /*! After construction and during initialization (when values are being added), the matrix coefficients + for each row are managed as separate segments of memory. This method moves the values for all rows + into one large contiguous array and eliminates internal storage that is not needed after matrix construction. Calling this + method can have a significant impact on memory costs and machine performance. + + If this object was constructed in View mode then this method can't make non-contiguous values contiguous and will + return a warning code of 1 if the viewed data isn't already contiguous. + + \note A call to this method will also call the OptimizeStorage method for the associated Epetra_CrsGraph object. If + the storage for this graph has already been optimized this additional call will have no effect. + + \return Integer error code, set to 0 if successful. + + \pre Filled()==true. + \pre If CV=View when the graph was constructed, then this method will be effective \only if the indices of the graph were already contiguous. In this case, the indices are left untouched and internal storage for the graph is minimized. + + \post StorageOptimized()==true, if successful. + \post Graph().StorageOptimized()==true, if successful. + + */ + int OptimizeStorage(); + + + //! Eliminates memory that is used for construction. Make consecutive row index sections contiguous. + int MakeDataContiguous() {EPETRA_CHK_ERR(OptimizeStorage()); return(0);} + //@} + + //! @name Extraction methods + //@{ + + //! Returns a copy of the specified global row in user-provided arrays. + /*! + \param GlobalRow - (In) Global row to extract. + \param ILength - (In) Length of Values and Indices. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + \param Indices - (Out) Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful, non-zero if global row is not owned by calling process +or if the number of entries in this row exceed the Length parameter. + */ + int ExtractGlobalRowCopy(int GlobalRow, int Length, int& NumEntries, double* Values, int* Indices) const; + + //! Returns a copy of the specified local row in user-provided arrays. + /*! + \param MyRow - (In) Local row to extract. + \param Length - (In) Length of Values and Indices. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + \param Indices - (Out) Extracted local column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. + + \pre IndicesAreLocal()==true + */ + int ExtractMyRowCopy(int MyRow, int Length, int& NumEntries, double* Values, int* Indices) const; + + //! Returns a copy of the specified global row values in user-provided array. + /*! + \param GlobalRow - (In) Global row to extract. + \param Length - (In) Length of Values. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + + \return Integer error code, set to 0 if successful. + */ + int ExtractGlobalRowCopy(int GlobalRow, int Length, int& NumEntries, double* Values) const; + + //! Returns a copy of the specified local row values in user-provided array. + /*! + \param MyRow - (In) Local row to extract. + \param Length - (In) Length of Values. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + + \return Integer error code, set to 0 if successful. + */ + int ExtractMyRowCopy(int MyRow, int Length, int& NumEntries, double* Values) const; + + //! Returns a copy of the main diagonal in a user-provided vector. + /*! + \param Diagonal - (Out) Extracted main diagonal. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int ExtractDiagonalCopy(Epetra_Vector& Diagonal) const; + + //! Returns a view of the specified global row values via pointers to internal data. + /*! + \param GlobalRow - (In) Global row to view. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + \param Indices - (Out) Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. Returns -1 of row not on this processor. + Returns -2 if matrix is not in global form (if FillComplete() has already been called). + + \pre IndicesAreGlobal()==true + */ + int ExtractGlobalRowView(int GlobalRow, int& NumEntries, double*& Values, int*& Indices) const; + + //! Returns a view of the specified local row values via pointers to internal data. + /*! + \param MyRow - (In) Local row to view. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + \param Indices - (Out) Extracted local column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. Returns -1 of row not on this processor. + Returns -2 if matrix is not in local form (if FillComplete() has \e not been called). + + \pre IndicesAreLocal()==true + */ + int ExtractMyRowView(int MyRow, int& NumEntries, double*& Values, int*& Indices) const; + + //! Returns a view of the specified global row values via pointers to internal data. + /*! + \param GlobalRow - (In) Global row to extract. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + + \return Integer error code, set to 0 if successful. + */ + int ExtractGlobalRowView(int GlobalRow, int& NumEntries, double*& Values) const; + + //! Returns a view of the specified local row values via pointers to internal data. + /*! + \param MyRow - (In) Local row to extract. + \param NumEntries - (Out) Number of nonzero entries extracted. + \param Values - (Out) Extracted values for this row. + + \return Integer error code, set to 0 if successful. + */ + int ExtractMyRowView(int MyRow, int& NumEntries, double*& Values) const; + //@} + + //! @name Computational methods + //@{ + + //! Returns the result of a Epetra_CrsMatrix multiplied by a Epetra_Vector x in y. + /*! + \param TransA - (In) If true, multiply by the transpose of matrix, otherwise just use matrix. + \param x - (In) An Epetra_Vector to multiply by. + \param y - (Out) An Epetra_Vector containing result. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int Multiply(bool TransA, const Epetra_Vector& x, Epetra_Vector& y) const; + int Multiply1(bool TransA, const Epetra_Vector& x, Epetra_Vector& y) const; + + + //! Returns the result of a Epetra_CrsMatrix multiplied by a Epetra_MultiVector X in Y. + /*! + \param TransA - (In) If true, multiply by the transpose of matrix, otherwise just use matrix. + \param X - (In) An Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Y - (Out) An Epetra_MultiVector of dimension NumVectorscontaining result. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + int Multiply1(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + //! Returns the result of a local solve using the Epetra_CrsMatrix on a Epetra_Vector x in y. + /*! This method solves a triangular system of equations asynchronously on each processor. + \param Upper - (In) If true, solve Uy = x, otherwise solve Ly = x. + \param Trans - (In) If true, solve transpose problem. + \param UnitDiagonal - (In) If true, assume diagonal is unit (whether it's stored or not). + \param x - (In) An Epetra_Vector to solve for. + \param y - (Out) An Epetra_Vector containing result. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_Vector& x, Epetra_Vector& y) const; + + //! Returns the result of a local solve using the Epetra_CrsMatrix a Epetra_MultiVector X in Y. + /*! This method solves a triangular system of equations asynchronously on each processor. + \param Upper - (In) If true, solve Uy = x, otherwise solve Ly = x. + \param Trans - (In) If true, solve transpose problem. + \param UnitDiagonal - (In) If true, assume diagonal is unit (whether it's stored or not). + \param X - (In) An Epetra_MultiVector of dimension NumVectors to solve for. + \param Y - (Out) An Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + //! Computes the inverse of the sum of absolute values of the rows of the Epetra_CrsMatrix, results returned in x. + /*! The vector x will return such that x[i] will contain the inverse of the sum of the absolute values of the entries in the + ith row of the \e this matrix. Using the resulting vector from this function as input to LeftScale() + will make the infinity norm of the resulting matrix exactly 1. + \warning The NormInf() method will not properly calculate the infinity norm for a matrix that has entries that are + replicated on multiple processors. In this case, if the rows are fully replicated, NormInf() will return a + value equal to the maximum number of processors that any individual row of the matrix is replicated on. + \param x - (Out) An Epetra_Vector containing the row sums of the \e this matrix. + \warning When rows are fully replicated on multiple processors, it is assumed that the distribution of x is + the same as the rows (RowMap())of \e this. When multiple processors contain partial sums for individual entries, the + distribution of x is assumed to be the same as the RangeMap() of \e this. When each row of \e this is + uniquely owned, the distribution of x can be that of the RowMap() or the RangeMap(). + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int InvRowSums(Epetra_Vector& x) const; + + //! Computes the max of absolute values of the rows of the Epetra_CrsMatrix, results returned in x. + /*! The vector x will return such that x[i] will contain the inverse of max of the absolute values of the entries in the ith + row of the \e this matrix. + \warning This method will not work when multiple processors contain partial sums for individual entries. + \param x - (Out) An Epetra_Vector containing the row maxs of the \e this matrix. + \warning When rows are fully replicated on multiple processors, it is assumed that the distribution of x is + the same as the rows (RowMap())of \e this. When each row of \e this is uniquely owned, the distribution of + x can be that of the RowMap() or the RangeMap(). + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int InvRowMaxs(Epetra_Vector& x) const; + + //! Scales the Epetra_CrsMatrix on the left with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the row number of A + and j denotes the column number of A. + \param x - (In) An Epetra_Vector to scale with. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post The matrix will be scaled as described above. + */ + int LeftScale(const Epetra_Vector& x); + + //! Computes the inverse of the sum of absolute values of the columns of the Epetra_CrsMatrix, results returned in x. + /*! The vector x will return such that x[j] will contain the inverse of the sum of the absolute values of the + entries in the jth column of the \e this matrix. Using the resulting vector from this function as input to + RightScale() will make the one norm of the resulting matrix exactly 1. + \warning The NormOne() method will not properly calculate the one norm for a matrix that has entries that are + replicated on multiple processors. In this case, if the columns are fully replicated, NormOne() will return a + value equal to the maximum number of processors that any individual column of the matrix is repliated on. + + \param x - (Out) An Epetra_Vector containing the column sums of the \e this matrix. + \warning When columns are fully replicated on multiple processors, it is assumed that the distribution of x is + the same as the columns (ColMap()) of \e this. When multiple processors contain partial sums for entries, the + distribution of x is assumed to be the same as the DomainMap() of \e this. When each column of \e this is + uniquely owned, the distribution of x can be that of the ColMap() or the DomainMap(). + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int InvColSums(Epetra_Vector& x) const; + + //! Computes the max of absolute values of the columns of the Epetra_CrsMatrix, results returned in x. + /*! The vector x will return such that x[j] will contain the inverse of max of the absolute values of the entries + in the jth row of the \e this matrix. + \warning This method will not work when multiple processors contain partial sums for individual entries. + \param x - (Out) An Epetra_Vector containing the column maxs of the \e this matrix. + \warning When columns are fully replicated on multiple processors, it is assumed that the distribution of x is + the same as the columns (ColMap()) of \e this. When each column of \e this is + uniquely owned, the distribution of x can be that of the ColMap() or the DomainMap(). + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int InvColMaxs(Epetra_Vector& x) const; + + //! Scales the Epetra_CrsMatrix on the right with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. + \param x - (In) The Epetra_Vector used for scaling \e this. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post The matrix will be scaled as described above. + */ + int RightScale(const Epetra_Vector& x); + //@} + + //! @name Matrix Properties Query Methods + //@{ + + + //! If FillComplete() has been called, this query returns true, otherwise it returns false. + bool Filled() const {return(Graph_.Filled());} + + //! If OptimizeStorage() has been called, this query returns true, otherwise it returns false. + bool StorageOptimized() const {return(StorageOptimized_);} + + //! If matrix indices has not been transformed to local, this query returns true, otherwise it returns false. + bool IndicesAreGlobal() const {return(Graph_.IndicesAreGlobal());} + + //! If matrix indices has been transformed to local, this query returns true, otherwise it returns false. + bool IndicesAreLocal() const {return(Graph_.IndicesAreLocal());} + + //! If matrix indices are packed into single array (done in OptimizeStorage()) return true, otherwise false. + bool IndicesAreContiguous() const {return(Graph_.IndicesAreContiguous());} + + //! If matrix is lower triangular in local index space, this query returns true, otherwise it returns false. + bool LowerTriangular() const {return(Graph_.LowerTriangular());} + + //! If matrix is upper triangular in local index space, this query returns true, otherwise it returns false. + bool UpperTriangular() const {return(Graph_.UpperTriangular());} + + //! If matrix has no diagonal entries in global index space, this query returns true, otherwise it returns false. + bool NoDiagonal() const {return(Graph_.NoDiagonal());} + + //@} + + //! @name Atribute access functions + //@{ + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f] + \warning The NormInf() method will not properly calculate the infinity norm for a matrix that has entries that are + replicated on multiple processors. */ + double NormInf() const; + + //! Returns the one norm of the global matrix. + /* Returns the quantity \f$ \| A \|_1\f$ such that + \f[\| A \|_1= \max_{1\lej\len} \sum_{i=1}^m |a_{ij}| \f]. + \warning The NormOne() method will not properly calculate the one norm for a matrix that has entries that are + replicated on multiple processors. + */ + double NormOne() const; + + //! Returns the frobenius norm of the global matrix. + /* Returns the quantity \f[ \| A \|_{Frobenius} = \sqrt{\sum_{i=1}^m \sum_{j=1}^n\|a_{ij}\|^2}\f] + \warning the NormFrobenius() method will not properly calculate the frobenius norm for a matrix that + has entries which are replicated on multiple processors. In that case, the returned + norm will be larger than the true norm. + */ + double NormFrobenius() const; + + //! Returns the number of nonzero entries in the global matrix. + /* + Note that if maps are defined such that some nonzeros appear on + multiple processors, then those nonzeros will be counted multiple times. + If the user wishes to assemble a matrix from overlapping submatrices, + they can use Epetra_FECrsMatrix. + */ + int NumGlobalNonzeros() const {return(Graph_.NumGlobalNonzeros());} + + //! Returns the number of global matrix rows. + int NumGlobalRows() const {return(Graph_.NumGlobalRows());} + + //! Returns the number of global matrix columns. + int NumGlobalCols() const {return(Graph_.NumGlobalCols());} + + //! Returns the number of global nonzero diagonal entries, based on global row/column index comparisons. + int NumGlobalDiagonals() const {return(Graph_.NumGlobalDiagonals());} + + //! Returns the number of nonzero entries in the calling processor's portion of the matrix. + int NumMyNonzeros() const {return(Graph_.NumMyNonzeros());} + + //! Returns the number of matrix rows owned by the calling processor. + int NumMyRows() const {return(Graph_.NumMyRows());} + + //! Returns the number of entries in the set of column-indices that appear on this processor. + /*! The set of column-indices that appear on this processor is the union of column-indices that + appear in all local rows. The size of this set isn't available until FillComplete() has been called. + \pre Filled()==true + */ + int NumMyCols() const {return(Graph_.NumMyCols());} + + //! Returns the number of local nonzero diagonal entries, based on global row/column index comparisons. + /*! + \pre Filled()==true + */ + int NumMyDiagonals() const {return(Graph_.NumMyDiagonals());} + + //! Returns the current number of nonzero entries in specified global row on this processor. + int NumGlobalEntries(int Row) const {return(Graph_.NumGlobalIndices(Row));} + + //! Returns the allocated number of nonzero entries in specified global row on this processor. + int NumAllocatedGlobalEntries(int Row) const{return(Graph_.NumAllocatedGlobalIndices(Row));} + + //! Returns the maximum number of nonzero entries across all rows on this processor. + /*! + \pre Filled()==true + */ + int MaxNumEntries() const {return(Graph_.MaxNumIndices());} + + //! Returns the maximum number of nonzero entries across all rows on all processors. + /*! + \pre Filled()==true + */ + int GlobalMaxNumEntries() const {return(Graph_.GlobalMaxNumIndices());} + + //! Returns the current number of nonzero entries in specified local row on this processor. + int NumMyEntries(int Row) const {return(Graph_.NumMyIndices(Row));} + + //! Returns the allocated number of nonzero entries in specified local row on this processor. + int NumAllocatedMyEntries(int Row) const {return(Graph_.NumAllocatedMyIndices(Row));} + + //! Returns the index base for row and column indices for this graph. + int IndexBase() const {return(Graph_.IndexBase());} + + + //! Returns true if the graph associated with this matrix was pre-constructed and therefore not changeable. + bool StaticGraph() {return(StaticGraph_);} + + //! Returns a reference to the Epetra_CrsGraph object associated with this matrix. + const Epetra_CrsGraph& Graph() const {return(Graph_);} + + //! Returns the Epetra_Map object associated with the rows of this matrix. + const Epetra_Map& RowMap() const {return((Epetra_Map &)Graph_.RowMap());} + + //! Replaces the current RowMap with the user-specified map object. + /** Replaces the current RowMap with the user-specified map object, but only + if currentmap->PointSameAs(newmap) is true. This is a collective function. + Returns 0 if map is replaced, -1 if not. + + \pre RowMap().PointSameAs(newmap)==true + */ + int ReplaceRowMap(const Epetra_BlockMap& newmap); + + //! Returns true if we have a well-defined ColMap, and returns false otherwise. + /*! \pre We have a well-defined ColMap if a) a ColMap was passed in at construction, + or b) the MakeColMap function has been called. (Calling either of the FillComplete functions + will result in MakeColMap being called.) + */ + bool HaveColMap() const {return(Graph_.HaveColMap());} + + //! Replaces the current ColMap with the user-specified map object. + /** Replaces the current ColMap with the user-specified map object, but only + if currentmap->PointSameAs(newmap) is true. This is a collective function. + Returns 0 if map is replaced, -1 if not. + + \pre ColMap().PointSameAs(newmap)==true + */ + int ReplaceColMap(const Epetra_BlockMap& newmap); + + + //! Returns the Epetra_Map object that describes the set of column-indices that appear in each processor's locally owned matrix rows. + /*!Note that if the matrix was constructed with only a row-map, then until FillComplete() is called, this method returns + a column-map that is a copy of the row-map. That 'initial' column-map is replaced with a computed column-map (that + contains the set of column-indices appearing in each processor's local portion of the matrix) when FillComplete() is + called. + + \pre HaveColMap()==true + */ + const Epetra_Map& ColMap() const {return((Epetra_Map &) Graph_.ColMap());} + + //! Returns the Epetra_Map object associated with the domain of this matrix operator. + /*! + \pre Filled()==true + */ + const Epetra_Map& DomainMap() const {return((Epetra_Map &)Graph_.DomainMap());} + + //! Returns the Epetra_Map object associated with the range of this matrix operator. + /*! + \pre Filled()==true + */ + const Epetra_Map& RangeMap() const {return((Epetra_Map &)Graph_.RangeMap());} + + //! Returns the Epetra_Import object that contains the import operations for distributed operations. + const Epetra_Import* Importer() const {return(Graph_.Importer());} + + //! Returns the Epetra_Export object that contains the export operations for distributed operations. + const Epetra_Export* Exporter() const {return(Graph_.Exporter());} + + //! Returns a pointer to the Epetra_Comm communicator associated with this matrix. + const Epetra_Comm& Comm() const {return(Epetra_DistObject::Comm());} + //@} + + //! @name Local/Global ID methods + //@{ + //! Returns the local row index for given global row index, returns -1 if no local row for this global row. + int LRID( int GRID) const {return(Graph_.LRID(GRID));} + + //! Returns the global row index for give local row index, returns IndexBase-1 if we don't have this local row. + int GRID( int LRID) const {return(Graph_.GRID(LRID));} + + //! Returns the local column index for given global column index, returns -1 if no local column for this global column. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + int LCID( int GCID) const {return(Graph_.LCID(GCID));} + + //! Returns the global column index for give local column index, returns IndexBase-1 if we don't have this local column. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + int GCID( int LCID) const {return(Graph_.GCID(LCID));} + + //! Returns true if the GRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyGRID(int GRID) const {return(Graph_.MyGRID(GRID));} + + //! Returns true if the LRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyLRID(int LRID) const {return(Graph_.MyLRID(LRID));} + + //! Returns true if the GCID passed in belongs to the calling processor in this map, otherwise returns false. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + bool MyGCID(int GCID) const {return(Graph_.MyGCID(GCID));} + + //! Returns true if the LRID passed in belongs to the calling processor in this map, otherwise returns false. + /*! + \pre HaveColMap()==true (If HaveColMap()==false, returns -1) + */ + bool MyLCID(int LCID) const {return(Graph_.MyLCID(LCID));} + + //! Returns true of GID is owned by the calling processor, otherwise it returns false. + bool MyGlobalRow(int GID) const {return(Graph_.MyGlobalRow(GID));} + //@} + + + //! @name I/O Methods + //@{ + + //! Print method + virtual void Print(ostream& os) const; + //@} + + //! @name Additional methods required to support the Epetra_Operator interface + //@{ + + //! Returns a character string describing the operator + const char* Label() const {return(Epetra_Object::Label());} + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param UseTranspose - (In) If true, multiply by the transpose of operator, otherwise just use operator. + + \return Always returns 0. + */ + int SetUseTranspose(bool UseTranspose) {UseTranspose_ = UseTranspose; return(0);} + + //! Returns the result of a Epetra_Operator applied to a Epetra_MultiVector X in Y. + /*! + \param X - (In) An Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Y -(Out) An Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { + return(Epetra_CrsMatrix::Multiply(Epetra_CrsMatrix::UseTranspose(), X, Y));} + + //! Returns the result of a Epetra_Operator inverse applied to an Epetra_MultiVector X in Y. + /*! In this implementation, we use several existing attributes to determine how virtual + method ApplyInverse() should call the concrete method Solve(). We pass in the UpperTriangular(), + the Epetra_CrsMatrix::UseTranspose(), and NoDiagonal() methods. The most notable warning is that + if a matrix has no diagonal values we assume that there is an implicit unit diagonal that should + be accounted for when doing a triangular solve. + + \param X - (In) An Epetra_MultiVector of dimension NumVectors to solve for. + \param Y - (Out) An Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + \pre Filled()==true + \post Unchanged. + */ + int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const { + return(Solve(UpperTriangular(), Epetra_CrsMatrix::UseTranspose(), NoDiagonal(), X, Y));} + + //! Returns true because this class can compute an Inf-norm. + bool HasNormInf() const {return(true);} + + //! Returns the current UseTranspose setting. + bool UseTranspose() const {return(UseTranspose_);} + + //! Returns the Epetra_Map object associated with the domain of this matrix operator. + const Epetra_Map& OperatorDomainMap() const + { + if (UseTranspose()) return(RangeMap()); + else return(DomainMap()); + } + + //! Returns the Epetra_Map object associated with the range of this matrix operator. + const Epetra_Map& OperatorRangeMap() const + { + if (UseTranspose()) return(DomainMap()); + else return(RangeMap()); + } + + //@} + //! @name Additional methods required to implement Epetra_RowMatrix interface + //@{ + + //! Return the current number of values stored for the specified local row. + /*! Similar to NumMyEntries() except NumEntries is returned as an argument + and error checking is done on the input value MyRow. + \param MyRow - (In) Local row. + \param NumEntries - (Out) Number of nonzero values. + + \return Integer error code, set to 0 if successful. + \pre None. + \post Unchanged. + */ + int NumMyRowEntries(int MyRow, int& NumEntries) const; + + //! Returns the Epetra_Map object associated with the rows of this matrix. + const Epetra_Map& RowMatrixRowMap() const {return(RowMap());} + + //! Returns the Epetra_Map object associated with columns of this matrix. + const Epetra_Map& RowMatrixColMap() const {return(ColMap());} + + //! Returns the Epetra_Import object that contains the import operations for distributed operations. + const Epetra_Import* RowMatrixImporter() const {return(Importer());} + + //@} + + //! @name Inlined Operator Methods + //@{ + + //! Inlined bracket operator for fast access to data. (Const and Non-const versions) + /*! No error checking and dangerous for optimization purposes. + \param Loc - (In) Local row. + + \return reference to pointer to locally indexed Loc row in matrix. + */ + inline double* operator[] (int Loc) { + if (StorageOptimized()){ int * ind = Graph().IndexOffset(); return(All_Values_+ind[Loc]);} + else return Values_[Loc];} + inline double* operator[] (int Loc) const { + if (StorageOptimized()){ int * ind = Graph().IndexOffset(); return(All_Values_+ind[Loc]);} + else return Values_[Loc];} + //@} + + //! @name Expert-only methods: These methods are intended for experts only and have some risk of changing in the future, since they rely on underlying data structure assumptions + //@{ + //! Returns internal data pointers associated with Crs matrix format. + /*! Returns data pointers to facilitate optimized code within external packages. + + \param IndexOffset - (Out) Extracted array of indices into Values[] and Indices[]. Local + row k is stored in Values[IndexOffset[k]:IndexOffset[k+1]-1] and + Indices[IndexOffset[k]:IndexOffset[k+1]-1]. + \param Values - (Out) Extracted values for all local rows. + \param Indices - (Out) Extracted local column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. Returns -1 if FillComplete has not been + performed or Storage has not been Optimized. + + \warning This method is intended for expert only, its use may require user code modifications in future versions of Epetra. + */ + int ExtractCrsDataPointers(int *& IndexOffset, int *& Indices, double *& Values) const { + if (StorageOptimized()) { + IndexOffset = Graph().IndexOffset(); + Indices = Graph().All_Indices(); + Values = All_Values(); + return (0); + } + else { IndexOffset = 0; Indices = 0; Values = 0; return (-1);} } + + //@} + + //! @name Deprecated methods: These methods still work, but will be removed in a future version + //@{ + + //! Use ColMap() instead. + const Epetra_Map& ImportMap() const {return((Epetra_Map&) Graph_.ImportMap());} + + //! Use FillComplete() instead. + int TransformToLocal(); + + //! Use FillComplete(const Epetra_Map& DomainMap, const Epetra_Map& RangeMap) instead. + int TransformToLocal(const Epetra_Map* DomainMap, const Epetra_Map* RangeMap); + + //@} + + + protected: + bool Allocated() const {return(Allocated_);} + int SetAllocated(bool Flag) {Allocated_ = Flag; return(0);} + double** Values() const { + if (StorageOptimized()) throw ReportError("This method: double** Values() cannot be called when StorageOptimized()==true", -1); + else return(Values_);} + double* All_Values() const { + if (!StorageOptimized()) throw ReportError("This method: double* All_Values()cannot be called when StorageOptimized()==false", -1); + else return(All_Values_);} + double* Values(int LocalRow) const { + if (StorageOptimized()) + if (Graph().StorageOptimized()) + return(All_Values_+Graph().IndexOffset()[LocalRow]); + else throw ReportError("This method: double* Values()cannot be called when StorageOptimized()==true and Graph().StorageOptimized()==false", -1); + else return(Values_[LocalRow]);} + + void InitializeDefaults(); + int Allocate(); + + int InsertValues(int LocalRow, int NumEntries, double* Values, int* Indices); + + int InsertOffsetValues(int GlobalRow, int NumEntries, double *Values, int *Indices); + int ReplaceOffsetValues(int GlobalRow, int NumEntries, double *Values, int *Indices); + int SumIntoOffsetValues(int GlobalRow, int NumEntries, double *Values, int *Indices); + void UpdateImportVector(int NumVectors) const; + void UpdateExportVector(int NumVectors) const; + void GeneralMV(double * x, double * y) const; + void GeneralMTV(double * x, double * y) const; + void GeneralMM(double ** X, int LDX, double ** Y, int LDY, int NumVectors) const; + void GeneralMTM(double ** X, int LDX, double ** Y, int LDY, int NumVectors) const; + void GeneralSV(bool Upper, bool Trans, bool UnitDiagonal, double * x, double * y) const; + void GeneralSM(bool Upper, bool Trans, bool UnitDiagonal, double ** X, int LDX, double ** Y, int LDY, int NumVectors) const; + + void SetStaticGraph(bool Flag) {StaticGraph_ = Flag;} + + int CheckSizes(const Epetra_SrcDistObject& A); + + int CopyAndPermute(const Epetra_SrcDistObject& Source, + int NumSameIDs, + int NumPermuteIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + int CopyAndPermuteCrsMatrix(const Epetra_CrsMatrix& A, + int NumSameIDs, + int NumPermuteIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + int CopyAndPermuteRowMatrix(const Epetra_RowMatrix& A, + int NumSameIDs, + int NumPermuteIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + + int PackAndPrepare(const Epetra_SrcDistObject& Source, + int NumExportIDs, + int* ExportLIDs, + int& LenExports, + char*& Exports, + int& SizeOfPacket, + int* Sizes, + bool& VarSizes, + Epetra_Distributor& Distor); + + int UnpackAndCombine(const Epetra_SrcDistObject& Source, + int NumImportIDs, + int* ImportLIDs, + int LenImports, + char* Imports, + int& SizeOfPacket, + Epetra_Distributor& Distor, + Epetra_CombineMode CombineMode, + const Epetra_OffsetIndex * Indexor); + + //! Sort column entries, row-by-row, in ascending order. + int SortEntries(); + + //! If SortEntries() has been called, this query returns true, otherwise it returns false. + bool Sorted() const {return(Graph_.Sorted());} + + //! Add entries that have the same column index. Remove redundant entries from list. + int MergeRedundantEntries(); + + //! If MergeRedundantEntries() has been called, this query returns true, otherwise it returns false. + bool NoRedundancies() const {return(Graph_.NoRedundancies());} + + void DeleteMemory(); + + Epetra_CrsGraph Graph_; + bool Allocated_; + bool StaticGraph_; + bool UseTranspose_; + bool constructedWithFilledGraph_; + bool matrixFillCompleteCalled_; + bool StorageOptimized_; + + double** Values_; + double* All_Values_; + mutable double NormInf_; + mutable double NormOne_; + mutable double NormFrob_; + + int NumMyRows_; + mutable Epetra_MultiVector* ImportVector_; + mutable Epetra_MultiVector* ExportVector_; + + Epetra_DataAccess CV_; + + bool squareFillCompleteCalled_; + private: + + // These are the pre-5.0 versions of solve. They are still faster that generic 5.0 solves, so we keep them around + int Solve1(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_Vector& x, Epetra_Vector& y) const; + int Solve1(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + +}; +#endif /* EPETRA_CRSMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_CrsSingletonFilter.h b/fastlib/trilinos/include/Epetra_CrsSingletonFilter.h new file mode 100644 index 0000000000..cd368e1421 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_CrsSingletonFilter.h @@ -0,0 +1,303 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_CRSSINGLETONFILTER_H +#define EPETRA_CRSSINGLETONFILTER_H + +#include "Epetra_Object.h" +#include "Epetra_CrsMatrix.h" +#include "Epetra_MapColoring.h" +#include "Epetra_SerialDenseVector.h" +class Epetra_LinearProblem; +class Epetra_Map; +class Epetra_MultiVector; +class Epetra_Import; +class Epetra_Export; +class Epetra_IntVector; + +//! Epetra_CrsSingletonFilter: A class for explicitly eliminating matrix rows and columns. + +/*! The Epetra_CrsSingletonFilter class takes an existing Epetra_LinearProblem object, analyzes + it structure and explicitly eliminates singleton rows and columns from the matrix and appropriately + modifies the RHS and LHS of the linear problem. The result of this process is a reduced system of equations + that is itself an Epetra_LinearProblem object. The reduced system can then be solved using any solver that + is understands an Epetra_LinearProblem. The solution for the full system is obtained by calling ComputeFullSolution(). + + Singleton rows are defined to be rows that have a single nonzero entry in the matrix. The equation associated with + this row can be explicitly eliminated because it involved only one variable. For example if row i has a single nonzero + value in column j, call it A(i,j), we can explicitly solve for x(j) = b(i)/A(i,j), where b(i) is the ith entry of the RHS + and x(j) is the jth entry of the LHS. + + Singleton columns are defined to be columns that have a single nonzero entry in the matrix. The variable associated + with this column is fully dependent, meaning that the solution for all other variables does not depend on it. If this + entry is A(i,j) then the ith row and jth column can be removed from the system and x(j) can be solved after the solution + for all other variables is determined. + + By removing singleton rows and columns, we can often produce a reduced system that is smaller and far less dense, and in + general having better numerical properties. + + The basic procedure for using this class is as follows: +
      +
    1. Construct full problem: Construct and Epetra_LinearProblem containing the "full" matrix, RHS and LHS. This is + done outside of Epetra_CrsSingletonFilter class. + Presumably, you have some reason to believe that this system may contain singletons. +
    2. Construct an Epetra_CrsSingletonFilter instance: Constructor needs no arguments. +
    3. Analyze matrix: Invoke the Analyze() method, passing in the Epetra_RowMatrix object from your full linear + problem mentioned in the first step above. +
    4. Go/No Go decision to construct reduced problem: + Query the results of the Analyze method using the SingletonsDetected() method. This method + returns "true" if there were singletons found in the matrix. You can also query any of the other methods + in the Filter Statistics section to determine if you want to proceed with the construction of the reduced system. +
    5. Construct reduced problem: + If, in the previous step, you determine that you want to proceed with the construction of the reduced problem, + you should next call the ConstructReducedProblem() method, passing in the full linear problem object from the first + step. This method will use the information from the Analyze() method to construct a reduce problem that has + explicitly eliminated the singleton rows, solved for the corresponding LHS values and updated the RHS. This + step will also remove singleton columns from the reduced system. Once the solution of the reduced problem is + is computed (via any solver that understands an Epetra_LinearProblem), you should call the ComputeFullSolution() + method to compute the LHS values assocaited with the singleton columns. +
    6. Solve reduced problem: Obtain a pointer to the reduced problem using the ReducedProblem() method. + Using the solver of your choice, solve the reduced system. +
    7. Compute solution to full problem: Once the solution the reduced problem is determined, the ComputeFullSolution() + method will place the reduced solution values into the appropriate locations of the full solution LHS and then + compute the values associated with column singletons. At this point, you have a complete solution to the original + full problem. +
    8. Solve a subsequent full problem that differs from the original problem only in values: It is often the case that the + structure of a problem will be the same for a sequence of linear problems. In this case, the UpdateReducedProblem() + method can be useful. After going through the above process one time, if you have a linear problem that is structural + \e identical to the previous problem, you can minimize memory and time costs by using the UpdateReducedProblem() + method, passing in the subsequent problem. Once you have called the UpdateReducedProblem() method, you can then + solve the reduce problem problem as you wish, and then compute the full solution as before. The pointer generated + by ReducedProblem() will not change when UpdateReducedProblem() is called. +
    +*/ + +class Epetra_CrsSingletonFilter { + + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_CrsSingletonFilter default constructor. + Epetra_CrsSingletonFilter(); + + //! Epetra_CrsSingletonFilter Destructor + virtual ~Epetra_CrsSingletonFilter(); + //@} + //! @name Analyze methods + //@{ + //! Analyze the input matrix, removing row/column pairs that have singletons. + /*! Analyzes the user's input matrix to determine rows and columns that should be explicitly + eliminated to create the reduced system. Look for rows and columns that have single entries. + These rows/columns + can easily be removed from the problem. + The results of calling this method are two MapColoring objects accessible via RowMapColors() and + ColMapColors() accessor methods. All rows/columns that would be eliminated in the reduced system + have a color of 1 in the corresponding RowMapColors/ColMapColors object. All kept rows/cols have a + color of 0. + */ + int Analyze(Epetra_RowMatrix * FullMatrix); + + //! Returns true if singletons were detected in this matrix (must be called after Analyze() to be effective). + bool SingletonsDetected() const {if (!AnalysisDone_) return(false); else return(RowMapColors_->MaxNumColors()>1);}; + //@} + + //! @name Reduce methods + //@{ + //! Return a reduced linear problem based on results of Analyze(). + /*! Creates a new Epetra_LinearProblem object based on the results of the Analyze phase. A pointer + to the reduced problem is obtained via a call to ReducedProblem(). + + \return Error code, set to 0 if no error. + */ + int ConstructReducedProblem(Epetra_LinearProblem * Problem); + + //! Update a reduced linear problem using new values. + /*! Updates an existing Epetra_LinearProblem object using new matrix, LHS and RHS values. The matrix + structure must be \e identical to the matrix that was used to construct the original reduced problem. + + \return Error code, set to 0 if no error. + */ + int UpdateReducedProblem(Epetra_LinearProblem * Problem); + + //@} + //! @name Methods to construct Full System Solution + //@{ + //! Compute a solution for the full problem using the solution of the reduced problem, put in LHS of FullProblem(). + /*! After solving the reduced linear system, this method can be called to compute the + solution to the original problem, assuming the solution for the reduced system is valid. The solution of the + unreduced, original problem will be in the LHS of the original Epetra_LinearProblem. + + */ + int ComputeFullSolution(); + //@} + //! @name Filter Statistics + //@{ + //! Return number of rows that contain a single entry, returns -1 if Analysis not performed yet. + int NumRowSingletons() const {return(NumGlobalRowSingletons_);}; + + //! Return number of columns that contain a single entry that are \e not associated with singleton row, returns -1 if Analysis not performed yet. + int NumColSingletons() const {return(NumGlobalColSingletons_);}; + + //! Return total number of singletons detected, returns -1 if Analysis not performed yet. + /*! Return total number of singletons detected across all processors. This method will not return a + valid result until after the Analyze() method is called. The dimension of the reduced system can + be computed by subtracting this number from dimension of full system. + \warning This method returns -1 if Analyze() method has not been called. + */ + int NumSingletons() const {return(NumColSingletons()+NumRowSingletons());}; + + //! Returns ratio of reduced system to full system dimensions, returns -1.0 if reduced problem not constructed. + double RatioOfDimensions() const {return(RatioOfDimensions_);}; + + //! Returns ratio of reduced system to full system nonzero count, returns -1.0 if reduced problem not constructed. + double RatioOfNonzeros() const {return(RatioOfNonzeros_);}; + + //@} + //! @name Attribute Access Methods + //@{ + + //! Returns pointer to the original unreduced Epetra_LinearProblem. + Epetra_LinearProblem * FullProblem() const {return(FullProblem_);}; + + //! Returns pointer to the derived reduced Epetra_LinearProblem. + Epetra_LinearProblem * ReducedProblem() const {return(ReducedProblem_);}; + + //! Returns pointer to Epetra_CrsMatrix from full problem. + Epetra_RowMatrix * FullMatrix() const {return(FullMatrix_);}; + + //! Returns pointer to Epetra_CrsMatrix from full problem. + Epetra_CrsMatrix * ReducedMatrix() const {return(ReducedMatrix_);}; + + //! Returns pointer to Epetra_MapColoring object: color 0 rows are part of reduced system. + Epetra_MapColoring * RowMapColors() const {return(RowMapColors_);}; + + //! Returns pointer to Epetra_MapColoring object: color 0 columns are part of reduced system. + Epetra_MapColoring * ColMapColors() const {return(ColMapColors_);}; + + //! Returns pointer to Epetra_Map describing the reduced system row distribution. + Epetra_Map * ReducedMatrixRowMap() const {return(ReducedMatrixRowMap_);}; + + //! Returns pointer to Epetra_Map describing the reduced system column distribution. + Epetra_Map * ReducedMatrixColMap() const {return(ReducedMatrixColMap_);}; + + //! Returns pointer to Epetra_Map describing the domain map for the reduced system. + Epetra_Map * ReducedMatrixDomainMap() const {return(ReducedMatrixDomainMap_);}; + + //! Returns pointer to Epetra_Map describing the range map for the reduced system. + Epetra_Map * ReducedMatrixRangeMap() const {return(ReducedMatrixRangeMap_);}; + //@} + + protected: + + + + // This pointer will be zero if full matrix is not a CrsMatrix. + Epetra_CrsMatrix * FullCrsMatrix() const {return(FullCrsMatrix_);}; + + const Epetra_Map & FullMatrixRowMap() const {return(FullMatrix()->RowMatrixRowMap());}; + const Epetra_Map & FullMatrixColMap() const {return(FullMatrix()->RowMatrixColMap());}; + const Epetra_Map & FullMatrixDomainMap() const {return((FullMatrix()->OperatorDomainMap()));}; + const Epetra_Map & FullMatrixRangeMap() const {return((FullMatrix()->OperatorRangeMap()));}; + void InitializeDefaults(); + int ComputeEliminateMaps(); + int Setup(Epetra_LinearProblem * Problem); + int InitFullMatrixAccess(); + int GetRow(int Row, int & NumIndices, int * & Indices); + int GetRowGCIDs(int Row, int & NumIndices, double * & Values, int * & GlobalIndices); + int GetRow(int Row, int & NumIndices, double * & Values, int * & Indices); + int CreatePostSolveArrays(const Epetra_IntVector & RowIDs, + const Epetra_MapColoring & RowMapColors, + const Epetra_IntVector & ColProfiles, + const Epetra_IntVector & NewColProfiles, + const Epetra_IntVector & ColHasRowWithSingleton); + + int ConstructRedistributeExporter(Epetra_Map * SourceMap, Epetra_Map * TargetMap, + Epetra_Export * & RedistributeExporter, + Epetra_Map * & RedistributeMap); + + Epetra_LinearProblem * FullProblem_; + Epetra_LinearProblem * ReducedProblem_; + Epetra_RowMatrix * FullMatrix_; + Epetra_CrsMatrix * FullCrsMatrix_; + Epetra_CrsMatrix * ReducedMatrix_; + Epetra_MultiVector * ReducedRHS_; + Epetra_MultiVector * ReducedLHS_; + + Epetra_Map * ReducedMatrixRowMap_; + Epetra_Map * ReducedMatrixColMap_; + Epetra_Map * ReducedMatrixDomainMap_; + Epetra_Map * ReducedMatrixRangeMap_; + Epetra_Map * OrigReducedMatrixDomainMap_; + Epetra_Import * Full2ReducedRHSImporter_; + Epetra_Import * Full2ReducedLHSImporter_; + Epetra_Export * RedistributeDomainExporter_; + + int * ColSingletonRowLIDs_; + int * ColSingletonColLIDs_; + int * ColSingletonPivotLIDs_; + double * ColSingletonPivots_; + + + int AbsoluteThreshold_; + double RelativeThreshold_; + + int NumMyRowSingletons_; + int NumMyColSingletons_; + int NumGlobalRowSingletons_; + int NumGlobalColSingletons_; + double RatioOfDimensions_; + double RatioOfNonzeros_; + + bool HaveReducedProblem_; + bool UserDefinedEliminateMaps_; + bool AnalysisDone_; + bool SymmetricElimination_; + + Epetra_MultiVector * tempExportX_; + Epetra_MultiVector * tempX_; + Epetra_MultiVector * tempB_; + Epetra_MultiVector * RedistributeReducedLHS_; + int * Indices_; + Epetra_SerialDenseVector Values_; + + Epetra_MapColoring * RowMapColors_; + Epetra_MapColoring * ColMapColors_; + bool FullMatrixIsCrsMatrix_; + int MaxNumMyEntries_; + + + private: + //! Copy constructor (defined as private so it is unavailable to user). + Epetra_CrsSingletonFilter(const Epetra_CrsSingletonFilter & Problem); + Epetra_CrsSingletonFilter & operator=(const Epetra_CrsSingletonFilter & Problem); +}; +#endif /* EPETRA_CRSSINGLETONFILTER_H */ diff --git a/fastlib/trilinos/include/Epetra_Data.h b/fastlib/trilinos/include/Epetra_Data.h new file mode 100644 index 0000000000..68db7dbf31 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Data.h @@ -0,0 +1,94 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_DATA_H +#define EPETRA_DATA_H + +//! Epetra_Data: The Epetra Base Data Class. +/*! The Epetra_Data class is a base class for all Epetra Data Classes. + It provides a mechanism so that one data object can be shared by multiple + class instances. However, it is meant only to be used internally by + another Epetra class. It does not provide smart pointer like capabilities. + Incrementing and decrementing the reference count, and deleting the + data class instance (if necessary), are duties of the Epetra class + utilizing Epetra_Data. + + All of Epetra_Data's methods are protected. This is because Epetra_Data + should never be used directly. Rather, a class that derives from + Epetra_Data should be used instead. For example, Epetra_MpiCommData or + Epetra_BlockMapData. + + DEVELOPER NOTES: + (1) Any class that inherits from Epetra_Data may need to define an + assignment operator, if it adds pointers. Epetra_Data doesn't have any, + and so the default (compiler-generated) assignment operator is good enough. + (2) The behavior of a derived class is left up to the + implementer(s) of that class. As such, it cannot be assumed that + just because a class inherits from Epetra_Data, that it supports copy + construction or assignment, or that it will perform as expected. +*/ + +class Epetra_Data { + protected: + //! @name Constructor/Destructor Methods + //@{ + + //! Epetra_Data Serial Constructor. + Epetra_Data(); + + //! Epetra_Data Copy Constructor. + /*! Reference count will be set to 1 on new instance.*/ + Epetra_Data(const Epetra_Data & Data); + + //! Epetra_Data Destructor. + virtual ~Epetra_Data(); + + //@} + + //! @name Reference-Counting Methods + //@{ + + //! Increment reference count + void IncrementReferenceCount(); + + //! Decrement reference count + void DecrementReferenceCount(); + + //! Get reference count + int ReferenceCount() const; + + //@} + + int ReferenceCount_; + +}; + +#endif /* EPETRA_DATA_H */ diff --git a/fastlib/trilinos/include/Epetra_DataAccess.h b/fastlib/trilinos/include/Epetra_DataAccess.h new file mode 100644 index 0000000000..7ff835d7b1 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_DataAccess.h @@ -0,0 +1,49 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_DATAACCESS_H +#define EPETRA_DATAACCESS_H +/*! \file Epetra_DataAccess.h + \brief Epetra_DataAccess Mode enumerable type + */ + +/*! \enum Epetra_DataAccess + If set to Copy, user data will be copied at construction. + If set to View, user data will be encapsulated and used throughout + the life of the object. +*/ +enum Epetra_DataAccess {Copy, /*!< User data will be copied at + construction. */ + View /*!< User data will be encapsulated and + used throughout the life of the object. */ + }; + +#endif // EPETRA_DATAACCESS_H diff --git a/fastlib/trilinos/include/Epetra_Directory.h b/fastlib/trilinos/include/Epetra_Directory.h new file mode 100644 index 0000000000..d220c41728 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Directory.h @@ -0,0 +1,99 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_DIRECTORY_H +#define EPETRA_DIRECTORY_H + +class Epetra_BlockMap; // Compiler needs forward reference +class Epetra_Map; + +//! Epetra_Directory: This class is a pure virtual class whose interface allows Epetra_Map and Epetr_BlockMap objects to reference non-local elements. + +/*! For Epetra_BlockMap objects, a Epetra_Directory object must be created by a call to + the Epetra_Comm CreateDirectory method. The Directory is needed to allow referencing + of non-local elements. + +*/ +class Epetra_Directory { + + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_Directory destructor. + virtual ~Epetra_Directory(){} + //@} + + //! @name Query method + //@{ + //! GetDirectoryEntries : Returns proc and local id info for non-local map entries + /*! Given a list of Global Entry IDs, this function returns the list of + processor IDs and local IDs on the owning processor that correspond + to the list of entries. If LocalEntries is 0, then local IDs are + not returned. If EntrySizes is nonzero, it will contain a list of corresponding + element sizes for the requested global entries. + \param In + NumEntries - Number of Global IDs being passed in. + \param In + GlobalEntries - List of Global IDs being passed in. + \param InOut + Procs - User allocated array of length at least NumEntries. On return contains list of processors + owning the Global IDs in question. + \param InOut + LocalEntries - User allocated array of length at least NumEntries. On return contains the local ID of + the global on the owning processor. If LocalEntries is zero, no local ID information is returned. + \param InOut + EntrySizes - User allocated array of length at least NumEntries. On return contains the size of the + object associated with this global ID. If LocalEntries is zero, no size information is returned. + + \param In + high_rank_sharing_procs Optional argument, defaults to true. If any GIDs appear on multiple + processors (referred to as "sharing procs"), this specifies whether the lowest-rank proc or the + highest-rank proc is chosen as the "owner". + + \return Integer error code, set to 0 if successful. + */ + virtual int GetDirectoryEntries( const Epetra_BlockMap& Map, + const int NumEntries, + const int * GlobalEntries, + int * Procs, + int * LocalEntries, + int * EntrySizes, + bool high_rank_sharing_procs=false) const = 0; + + //!GIDsAllUniquelyOwned: returns true if all GIDs appear on just one processor. + /*! If any GIDs are owned by multiple processors, returns false. + */ + virtual bool GIDsAllUniquelyOwned() const = 0; + //@} +}; + +#endif /* EPETRA_DIRECTORY_H */ diff --git a/fastlib/trilinos/include/Epetra_DistObject.h b/fastlib/trilinos/include/Epetra_DistObject.h new file mode 100644 index 0000000000..4b554afd55 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_DistObject.h @@ -0,0 +1,270 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_DISTOBJECT_H +#define EPETRA_DISTOBJECT_H +#include "Epetra_Object.h" +#include "Epetra_SrcDistObject.h" +#include "Epetra_BlockMap.h" +class Epetra_Comm; +class Epetra_Import; +class Epetra_Export; +class Epetra_Distributor; +class Epetra_OffsetIndex; + +//! Epetra_DistObject: A class for constructing and using dense multi-vectors, vectors and matrices in parallel. + +/*! The Epetra_DistObject is a base class for all Epetra distributed global objects. It provides the basic + mechanisms and interface specifications for importing and exporting operations using Epetra_Import and + Epetra_Export objects. + + Distributed Global vs. Replicated Local. + +
      +
    • Distributed Global objects - In most instances, a distributed object will be partitioned + across multiple memory images associated with multiple processors. In this case, there is + a unique copy of each element and elements are spread across all processors specified by + the Epetra_Comm communicator. +
    • Replicated Local Objects - Some algorithms use objects that are too small to + be distributed across all processors, the Hessenberg matrix in a GMRES + computation. In other cases, such as with block iterative methods, block dot product + functions produce small + dense matrices that are required by all processors. Replicated local objectss handle + these types of situation. +
    + +*/ + +//========================================================================== +class Epetra_DistObject: public Epetra_Object, public virtual Epetra_SrcDistObject { + + public: + //! @name Constructors/Destructor + //@{ + //! Basic Epetra_DistObject constuctor. + /*! Creates a Epetra_DistObject object. + + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + + \warning Note that, because Epetra_LocalMap + derives from Epetra_Map and Epetra_Map derives from Epetra_BlockMap, this constructor works + for all three types of Epetra map classes. + + \return Pointer to a Epetra_DistObject. + + */ + Epetra_DistObject(const Epetra_BlockMap& Map); + + /*! Creates a Epetra_DistObject object. + + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + + \warning Note that, because Epetra_LocalMap + derives from Epetra_Map and Epetra_Map derives from Epetra_BlockMap, this constructor works + for all three types of Epetra map classes. + \param In + Label - An identifier for this object. By default, set to the name of the object class. + + \return Pointer to a Epetra_DistObject. + + */ + Epetra_DistObject(const Epetra_BlockMap& Map, const char* const Label); + + //! Epetra_DistObject copy constructor. + + Epetra_DistObject(const Epetra_DistObject& Source); + + + //! Epetra_DistObject destructor. + virtual ~Epetra_DistObject(); + //@} + + //! @name Import/Export Methods + //@{ + + //! Imports an Epetra_DistObject using the Epetra_Import object. + /*! + \param In + Source - Distributed object that will be imported into the "\e this" object. + \param In + Importer - A Epetra_Import object specifying the communication required. + + \param In + CombineMode - A Epetra_CombineMode enumerated type specifying how results should be combined on the + receiving processor. + + \return Integer error code, set to 0 if successful. + */ + int Import(const Epetra_SrcDistObject& A, const Epetra_Import& Importer, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex * Indexor = 0); + + //! Imports an Epetra_DistObject using the Epetra_Export object. + /*! + \param In + Source - Distributed object that will be imported into the "\e this" object. + \param In + Exporter - A Epetra_Export object specifying the communication required. + + \param In + CombineMode - A Epetra_CombineMode enumerated type specifying how results should be combined on the + receiving processor. + + \return Integer error code, set to 0 if successful. + */ + int Import(const Epetra_SrcDistObject& A, const Epetra_Export& Exporter, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex * Indexor = 0); + + //! Exports an Epetra_DistObject using the Epetra_Import object. + /*! + \param In + Source - Distributed object that will be exported to the "\e this" object. + \param In + Importer - A Epetra_Import object specifying the communication required. + + \param In + CombineMode - A Epetra_CombineMode enumerated type specifying how results should be combined on the + receiving processor. + + \return Integer error code, set to 0 if successful. + */ + int Export(const Epetra_SrcDistObject& A, const Epetra_Import & Importer, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex * Indexor = 0); + + //! Exports an Epetra_DistObject using the Epetra_Export object. + /*! + \param In + Source - Distributed object that will be exported to the "\e this" multivector. + \param In + Exporter - A Epetra_Export object specifying the communication required. + + \param In + CombineMode - A Epetra_CombineMode enumerated type specifying how results should be combined on the + receiving processor. + + \return Integer error code, set to 0 if successful. + */ + int Export(const Epetra_SrcDistObject& A, const Epetra_Export& Exporter, Epetra_CombineMode CombineMode, const Epetra_OffsetIndex * Indexor = 0); + //@} + + //! @name Attribute accessor methods + //@{ + //! Returns the address of the Epetra_BlockMap for this multi-vector. + const Epetra_BlockMap& Map() const {return(Map_);}; + + //! Returns the address of the Epetra_Comm for this multi-vector. + const Epetra_Comm& Comm() const {return(*Comm_);}; + + //! Returns true if this multi-vector is distributed global, i.e., not local replicated. + bool DistributedGlobal() const {return(DistributedGlobal_);}; + //@} + + //! @name Miscellaneous + //@{ + //! Print method + virtual void Print(ostream& os) const; + //@} + + protected: + + + //! @name Internal utilities + //@{ + //! Perform actual transfer (redistribution) of data across memory images, using Epetra_Distributor object. + virtual int DoTransfer(const Epetra_SrcDistObject& A, + Epetra_CombineMode CombineMode, + int NumSameIDs, + int NumPermuteIDs, + int NumRemoteIDs, + int NumExportIDs, + int* PermuteToLIDs, + int* PermuteFromLIDs, + int* RemoteLIDs, + int* ExportLIDs, + int& LenExports, + char*& Exports, + int& LenImports, + char*& Imports, + Epetra_Distributor& Distor, + bool DoReverse, + const Epetra_OffsetIndex * Indexor ); + //@} + + // These methods must be implemented by derived class + + //! @name Virtual methods to be implemented by derived class + //@{ + //! Allows the source and target (\e this) objects to be compared for compatibility, return nonzero if not. + virtual int CheckSizes(const Epetra_SrcDistObject& Source) = 0; + //! Perform ID copies and permutations that are on processor. + virtual int CopyAndPermute(const Epetra_SrcDistObject& Source, + int NumSameIDs, + int NumPermuteIDs, + int * PermuteToLIDs, + int * PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor) = 0; + + //! Perform any packing or preparation required for call to DoTransfer(). + virtual int PackAndPrepare(const Epetra_SrcDistObject& Source, + int NumExportIDs, + int* ExportLIDs, + int& LenExports, + char*& Exports, + int& SizeOfPacket, + int* Sizes, + bool & VarSizes, + Epetra_Distributor& Distor) = 0; + + //! Perform any unpacking and combining after call to DoTransfer(). + virtual int UnpackAndCombine(const Epetra_SrcDistObject& Source, + int NumImportIDs, + int* ImportLIDs, + int LenImports, + char* Imports, + int& SizeOfPacket, + Epetra_Distributor& Distor, + Epetra_CombineMode CombineMode, + const Epetra_OffsetIndex * Indexor) = 0; + + //@} + Epetra_BlockMap Map_; + const Epetra_Comm* Comm_; + bool DistributedGlobal_; + char* Exports_; + char* Imports_; + int LenExports_; + int LenImports_; + int *Sizes_; + + private: + Epetra_DistObject& operator=(const Epetra_DistObject& src); + +}; + +#endif /* EPETRA_DISTOBJECT_H */ diff --git a/fastlib/trilinos/include/Epetra_Distributor.h b/fastlib/trilinos/include/Epetra_Distributor.h new file mode 100644 index 0000000000..ab70f08a22 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Distributor.h @@ -0,0 +1,177 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_DISTRIBUTOR_H +#define EPETRA_DISTRIBUTOR_H + +//! Epetra_Distributor: The Epetra Gather/Scatter Setup Base Class. +/*! The Epetra_Distributor class is an interface that encapsulates the general + information and services needed for other Epetra classes to perform gather/scatter + operations on a parallel computer. + An Epetra_Distributor object is actually produced by calling a method in the Epetra_Comm class. + + Epetra_Distributor has default implementations, via Epetra_SerialDistributor and + Epetra_MpiDistributor, for both serial execution and MPI + distributed memory execution. It is meant to insulate the user from + the specifics of communication that are not required for normal + manipulation of linear algebra objects.. +*/ + +#include "Epetra_Object.h" +class Epetra_Distributor { + + public: + //! @name Constructor and Destructor + //@{ + //! Epetra_Distributor clone constructor. + virtual Epetra_Distributor * Clone() = 0; + //! Epetra_Distributor Destructor. + virtual ~Epetra_Distributor(){}; + //@} + + + //! @name Gather/Scatter Constructors + //@{ + //! Create Distributor object using list of process IDs to which we export + /*! Take a list of Process IDs and construct a plan for efficiently scattering to these processes. + Return the number of IDs being sent to me. + \param NumExportIDs In + Number of IDs that need to be sent from this processor. + \param ExportPIDs In + List of processors that will get the exported IDs. + \param Deterministic In + No op. + \param NumRemoteIDs Out + Number of IDs this processor will be receiving. + */ + virtual int CreateFromSends( const int & NumExportIDs, + const int * ExportPIDs, + bool Deterministic, + int & NumRemoteIDs ) = 0; + + //! Create Distributor object using list of Remote global IDs and corresponding PIDs + /*! Take a list of global IDs and construct a plan for efficiently scattering to these processes. + Return the number and list of IDs being sent by me. + \param NumRemoteIDs In + Number of IDs this processor will be receiving. + \param RemoteGIDs In + List of IDs that this processor wants. + \param RemotePIDs In + List of processors that will send the remote IDs. + \param Deterministic In + No op. + \param NumExportIDs Out + Number of IDs that need to be sent from this processor. + \param ExportPIDs Out + List of processors that will get the exported IDs. + */ + virtual int CreateFromRecvs( const int & NumRemoteIDs, + const int * RemoteGIDs, + const int * RemotePIDs, + bool Deterministic, + int & NumExportIDs, + int *& ExportGIDs, + int *& ExportPIDs) = 0; + //@} + + //! @name Execute Gather/Scatter Operations (Constant size objects) + //@{ + + //! Execute plan on buffer of export objects in a single step + virtual int Do( char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs) = 0; + + //! Execute reverse of plan on buffer of export objects in a single step + virtual int DoReverse( char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs ) = 0; + + //! Post buffer of export objects (can do other local work before executing Waits) + virtual int DoPosts( char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs ) = 0; + + //! Wait on a set of posts + virtual int DoWaits() = 0; + + //! Do reverse post of buffer of export objects (can do other local work before executing Waits) + virtual int DoReversePosts( char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs) = 0; + + //! Wait on a reverse set of posts + virtual int DoReverseWaits() = 0; + //@} + + //! @name Execute Gather/Scatter Operations (Non-constant size objects) + //@{ + + //! Execute plan on buffer of export objects in a single step (object size may vary) + virtual int Do( char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs) = 0; + + //! Execute reverse of plan on buffer of export objects in a single step (object size may vary) + virtual int DoReverse( char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs) = 0; + + //! Post buffer of export objects (can do other local work before executing Waits) + virtual int DoPosts( char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs) = 0; + + //! Do reverse post of buffer of export objects (can do other local work before executing Waits) + virtual int DoReversePosts( char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs) = 0; + + //@} + + //! @name Print object to an output stream + //@{ + virtual void Print(ostream & os) const = 0; + //@} +}; +#endif /* EPETRA_DISTRIBUTOR_H */ diff --git a/fastlib/trilinos/include/Epetra_Export.h b/fastlib/trilinos/include/Epetra_Export.h new file mode 100644 index 0000000000..6cc369711a --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Export.h @@ -0,0 +1,300 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_EXPORT_H +#define EPETRA_EXPORT_H + +#include "Epetra_Object.h" +#include "Epetra_BlockMap.h" + +class Epetra_Distributor; + +//! Epetra_Export: This class builds an export object for efficient exporting of off-processor elements. + +/*! Epetra_Export is used to construct a communication plan that can be called repeatedly by computational + classes such the Epetra matrix, vector and multivector classes to efficiently send data to a target processor. + + This class currently has one constructor, taking two Epetra_Map or Epetra_BlockMap objects. The + first map specifies the global IDs that are owned by the calling processor. The second map specifies + the global IDs of elements that we want to export to later. +*/ + +class Epetra_Export: public Epetra_Object { + + public: + + //! Constructs a Epetra_Export object from the source and target maps. + /*! This constructor builds an Epetra_Export object by comparing the GID lists of the source and + target maps. + \param SourceMap (In) Map containing the GIDs from which data should be exported from each processor to + the target map whenever an export operation is performed using this exporter. + \param TargetMap (In) Map containing the GIDs that should be used for exporting data. + + \warning Note that the TargetMap \e must have GIDs uniquely owned, each GID of the target map can occur only once. + +Builds an export object that will transfer objects built with SourceMap to objects built with TargetMap. + + A Epetra_Export object categorizes the elements of the target map into three sets as follows: +
      +
    1. All elements in the target map that have the same GID as the corresponding element of the source map, + starting with the first + element in the target map, going up to the first element that is different from the source map. The number of + these IDs is returned by NumSameIDs(). +
    2. All elements that are local to the processor, but are not part of the first set of elements. These elements + have GIDs that are owned by the calling processor, but at least the first element of this list is permuted. + Even if subsequent elements are not permuted, they are included in this list. The number of permuted elements + is returned by NumPermutedIDs(). The list of elements (local IDs) in the source map that are permuted can be + found in the list PermuteFromLIDs(). The list of elements (local IDs) in the target map that are the new locations + of the source elements can be found in the list PermuteToLIDs(). +
    3. All remaining elements of the target map correspond to global IDs that are owned by remote processors. The number + of these elements is returned by NumRemoteIDs() and the list of these is returned by RemoteLIDs(). +
    + +Given the above information, the Epetra_Export constructor builds a list of elements that must be communicated to other +processors as a result of export requests. The number of exported elements (where multiple sends of the same element +to different processors is counted) is returned by NumExportIDs(). The local IDs to be sent are returned by the list +ExportLIDs(). The processors to which each of the elements will be sent in returned in a list of the same length by +ExportPIDs(). + +The total number of elements that will be sent by the calling processor is returned by NumSend(). The total number of +elements that will be received is returned by NumRecv(). + + +The following example illustrates the basic concepts. + +Assume we have 3 processors and 9 global elements with each processor owning 3 elements as follows +\verbatim + PE 0 Elements | PE 1 Elements | PE 2 Elements + 0 1 2 3 4 5 6 7 8 +\endverbatim + +The above layout essentially defines the target map argument of the export object. + +This could correspond to a 9-entry forcing vector with the first three entries on PE 0, and so on. +Suppose that the entries of this forcing vector are computed by integrating over linear "hat" functions: + +\verbatim +^ ^ ^ ^ ^ ^ ^ ^ ^ + \/ \/ \/ \/ \/ \/ \/ \/ + /\ /\ /\ /\ /\ /\ /\ /\ ++--+--+--+--+--+--+--+--+ +0 1 2 3 4 5 6 7 8 + + +\endverbatim + +In this case, PE 0 will make contributions to entries 0 through 3, PE 1 will make contributions to entries 2 through +6 and PE 2 will make contributions to entries 5 through 8. A convenient way to compute these contributions is to create +a forcing vector with replicated entries for the shared contributions. Specifically the following SourceMap works for +this scenario: + +\verbatim + + PE 0 Elements | PE 1 Elements | PE 2 Elements + 0 1 2 3 2 3 4 5 6 5 6 7 8 +\endverbatim + +A vector constructed using this SourceMap can be used to collect each processor's contributions to the forcing vector. +Note that the ordering of the elements on each processor is not unique, but has been chosen for illustration. + +With these two maps passed into the Epetra_Export constructor, we get the following attribute definitions: + +On PE 0: + +\verbatim +NumSameIDs = 3 + +NumPermuteIDs = 0 +PermuteToLIDs = 0 +PermuteFromLIDs = 0 + +NumRemoteIDs = 1 +RemoteLIDs = [2] + +NumExportIDs = 1 +ExportLIDs = [3] +ExportPIDs = [1] + +NumSend = 1 +NumRecv = 1 + +\endverbatim + +On PE 1: + +\verbatim +NumSameIDs = 0 + +NumPermuteIDs = 3 +PermuteToLIDs = [0, 1, 2] +PermuteFromLIDs = [1, 2, 3] + +NumRemoteIDs = 2 +RemoteLIDs = [0, 2] + +NumExportIDs = 2 +ExportLIDs = [0, 4] +ExportPIDs = [0, 2] + +NumSend = 2 +NumRecv = 2 + +\endverbatim + +On PE 2: + +\verbatim +NumSameIDs = 0 + +NumPermuteIDs = 3 +PermuteToLIDs = [0, 1, 2] +PermuteFromLIDs = [1, 2, 3] + +NumRemoteIDs = 1 +RemoteLIDs = [0] + +NumExportIDs = 1 +ExportLIDs = [0] +ExportPIDs = [1] + +NumSend = 1 +NumRecv = 1 + +\endverbatim + + + Using Epetra_Export Objects + +Once a Epetra_Export object has been constructed, it can be used by any of the Epetra classes that support distributed global +objects, namely Epetra_Vector, Epetra_MultiVector, Epetra_CrsGraph, Epetra_CrsMatrix and Epetra_VbrMatrix. +All of these classes have Export and Export methods that will fill new objects whose distribution is described by +the target map, taking elements from the source object whose distribution is described by the source map. Details of usage +for each class is given in the appropriate class documentation. + +In the above example, if x_integrate is constructed using the SourceMap and then filled with local contributions, and x_force +is constructed using the target map, the following operation will fill x_force with the combined results of x_integrate: +\verbatim +x_force.Export(x_integrate, exporter, Add); +\endverbatim +The third argument above tells the export operation to add results that come from multiple processors for the same GID. + +Epetra_Export objects can also be used by Import operations to perform the reverse operation. For example, if x_force in the +above example had boundary conditions that should be sent to processors that share a boundary element, the following operation +would send replicated values to x_integrate: +\verbatim +x_integrate.Import(x_force, exporter, Insert); +\endverbatim +At the end of this operation, x_integrate would have replicated values from x_force of entries 2 and 3 on PEs 0 and 1, +and entries 5 and 6 on PEs 1 and 2. + + */ + Epetra_Export( const Epetra_BlockMap & SourceMap, const Epetra_BlockMap & TargetMap ); + + //! Epetra_Export copy constructor. + Epetra_Export(const Epetra_Export& Exporter); + + //! Epetra_Export destructor. + + virtual ~Epetra_Export(void); + //! Returns the number of elements that are identical between the source and target maps, up to the first different ID + int NumSameIDs() const {return(NumSameIDs_);}; + + //! Returns the number of elements that are local to the calling processor, but not part of the first NumSameIDs() elements. + int NumPermuteIDs() const {return(NumPermuteIDs_);}; + + //! List of elements in the source map that are permuted. + int * PermuteFromLIDs () const {return(PermuteFromLIDs_);}; + //! List of elements in the target map that are permuted. + int * PermuteToLIDs () const {return(PermuteToLIDs_);}; + + //! Returns the number of elements that are not on the calling processor. + int NumRemoteIDs() const {return(NumRemoteIDs_);}; + + //! List of elements in the target map that are coming from other processors. + int * RemoteLIDs() const {return(RemoteLIDs_);}; + + //! Returns the number of elements that must be sent by the calling processor to other processors. + int NumExportIDs () const {return(NumExportIDs_);}; + + //! List of elements that will be sent to other processors. + int * ExportLIDs () const {return(ExportLIDs_);}; + + //! List of processors to which elements will be sent, ExportLIDs() [i] will be sent to processor ExportPIDs() [i]. + int * ExportPIDs () const {return(ExportPIDs_);}; + + //! Total number of elements to be sent. + int NumSend() const {return(NumSend_);}; + + //! Total number of elements to be received. + int NumRecv() const {return(NumRecv_);}; + + //! Returns the SourceMap used to construct this exporter + const Epetra_BlockMap & SourceMap() const {return(SourceMap_);}; + + //! Returns the TargetMap used to construct this exporter + const Epetra_BlockMap & TargetMap() const {return(TargetMap_);}; + + Epetra_Distributor & Distributor() const {return(*Distor_);}; + + //! @name Print object to an output stream + //@{ + virtual void Print(ostream & os) const; + //@} + protected: + + friend class Epetra_BlockMap; + + private: + Epetra_Export& operator=(const Epetra_Export& src); + + Epetra_BlockMap TargetMap_; + Epetra_BlockMap SourceMap_; + + int NumSameIDs_; + int NumPermuteIDs_; + int * PermuteToLIDs_; + int * PermuteFromLIDs_; + int NumRemoteIDs_; + int * RemoteLIDs_; + + int NumExportIDs_; + int * ExportLIDs_; + int * ExportPIDs_; + + int NumSend_; + int NumRecv_; + + Epetra_Distributor * Distor_; + + +}; + +#endif /* EPETRA_EXPORT_H */ diff --git a/fastlib/trilinos/include/Epetra_FECrsGraph.h b/fastlib/trilinos/include/Epetra_FECrsGraph.h new file mode 100644 index 0000000000..fd7d338dd9 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_FECrsGraph.h @@ -0,0 +1,176 @@ +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_FECRSGRAPH_H +#define EPETRA_FECRSGRAPH_H + +#include "Epetra_Map.h" +#include "Epetra_CrsGraph.h" + +/** + Epetra Finite-Element CrsGraph. This class provides the ability to insert + indices into a matrix-graph, where the indices represent dense submatrices + such as element-stiffnesses that might arise from a finite-element + application. + + In a parallel setting, indices may be submitted on the local processor + for rows that do not reside in the local portion of the row-map. After + all indices have been submitted, the GlobalAssemble method gathers all + non-local graph rows to the appropriate 'owning' processors (an owning + processor is a processor which has the row in its row-map). + */ +class Epetra_FECrsGraph : public Epetra_CrsGraph { + public: + + /** Constructor */ + Epetra_FECrsGraph(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + int* NumIndicesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor */ + Epetra_FECrsGraph(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + int NumIndicesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor */ + Epetra_FECrsGraph(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + const Epetra_BlockMap& ColMap, + int* NumIndicesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor */ + Epetra_FECrsGraph(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + const Epetra_BlockMap& ColMap, + int NumIndicesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor */ + Epetra_FECrsGraph(const Epetra_FECrsGraph& Graph); + + /** Destructor */ + virtual ~Epetra_FECrsGraph(); + + //Let the compiler know we intend to overload the base-class function + //InsertGlobalIndices rather than hide it. + using Epetra_CrsGraph::InsertGlobalIndices; + + /** Insert a rectangular, dense 'submatrix' of entries (matrix nonzero + positions) into the graph. + + @param numRows Number of rows in the submatrix. + @param rows List of row-numbers for the submatrix. + @param numCols Number of columns in the submatrix. + @param cols List of column-indices that will be used for each row in + the 'rows' list. + */ + int InsertGlobalIndices(int numRows, const int* rows, + int numCols, const int* cols); + + /** Gather any overlapping/shared data into the non-overlapping partitioning + defined by the Map that was passed to this matrix at construction time. + Data imported from other processors is stored on the owning processor + with a "sumInto" or accumulate operation. + This is a collective method -- every processor must enter it before any + will complete it. + + ***NOTE***: When GlobalAssemble() calls FillComplete(), it passes the + arguments 'DomainMap()' and 'RangeMap()', which are the map attributes + held by the base-class CrsMatrix and its graph. If a rectangular matrix + is being assembled, the domain-map and range-map must be specified by + calling the other overloading of this method. Otherwise, GlobalAssemble() + has no way of knowing what these maps should really be. + + + @param callFillComplete option argument, defaults to true. + Determines whether GlobalAssemble() internally calls the + FillComplete() method on this matrix. + + @return error-code 0 if successful, non-zero if some error occurs + */ + int GlobalAssemble(bool callFillComplete=true); + + /** Gather any overlapping/shared data into the non-overlapping partitioning + defined by the Map that was passed to this matrix at construction time. + Data imported from other processors is stored on the owning processor + with a "sumInto" or accumulate operation. + This is a collective method -- every processor must enter it before any + will complete it. + + ***NOTE***: When GlobalAssemble() (the other overloading of this method) + calls FillComplete(), it passes the arguments 'DomainMap()' and + 'RangeMap()', which are the map attributes already held by the base-class + CrsMatrix and its graph. If a rectangular matrix is being assembled, the + domain-map and range-map must be specified. Otherwise, GlobalAssemble() + has no way of knowing what these maps should really be. + + + @param domain_map user-supplied domain map for this matrix + + @param range_map user-supplied range map for this matrix + + @param callFillComplete option argument, defaults to true. + Determines whether GlobalAssemble() internally calls the + FillComplete() method on this matrix. + + @return error-code 0 if successful, non-zero if some error occurs + */ + int GlobalAssemble(const Epetra_Map& domain_map, + const Epetra_Map& range_map, + bool callFillComplete=true); + + private: + void DeleteMemory(); + int InsertNonlocalRow(int row, int offset); + int InputNonlocalIndices(int row, + int numCols, + const int* cols); + int InputNonlocalIndex(int rowoffset, + int col); + + int myFirstRow_; + int myNumRows_; + bool ignoreNonLocalEntries_; + + int numNonlocalRows_; + int* nonlocalRows_; + int* nonlocalRowLengths_; + int* nonlocalRowAllocLengths_; + int** nonlocalCols_; + + Epetra_FECrsGraph & operator=(const Epetra_FECrsGraph& Graph); + + +};//class Epetra_FECrsGraph + +#endif diff --git a/fastlib/trilinos/include/Epetra_FECrsMatrix.h b/fastlib/trilinos/include/Epetra_FECrsMatrix.h new file mode 100644 index 0000000000..f26f4d2c03 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_FECrsMatrix.h @@ -0,0 +1,581 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_FECRSMATRIX_H +#define EPETRA_FECRSMATRIX_H + +#include +class Epetra_Map; +class Epetra_IntSerialDenseVector; +class Epetra_SerialDenseMatrix; + +/** Epetra Finite-Element CrsMatrix. This class provides the ability to + input finite-element style sub-matrix data, including sub-matrices with + non-local rows (which could correspond to shared finite-element nodes for + example). This class inherits Epetra_CrsMatrix, and so all Epetra_CrsMatrix + functionality is also available. + + It is intended that this class will be used as follows: +
      +
    • Construct with either a map or graph that describes a (non-overlapping) + data distribution. +
    • Input data, including non-local data, using the methods + InsertGlobalValues(), SumIntoGlobalValues() and/or ReplaceGlobalValues(). +
    • Call the method GlobalAssemble(), which gathers all non-local data + onto the owning processors as determined by the map provided at + construction. Users should note that the GlobalAssemble() method has an + optional argument which determines whether GlobalAssemble() in turn calls + FillComplete() after the data-exchange has occurred. If not explicitly + supplied, this argument defaults to true. + ***NOTE***: When GlobalAssemble() calls FillComplete(), it passes the + arguments 'DomainMap()' and 'RangeMap()', which are the map attributes + held by the base-class CrsMatrix and its graph. If a rectangular matrix + is being assembled, the correct domain-map and range-map must be passed to + GlobalAssemble (there are two overloadings of this method) -- otherwise, it + has no way of knowing what these maps should really be. +
    + + Sub-matrix data, which is assumed to be a rectangular 'table' of + coefficients accompanied by 'scatter-indices', can be provided in three + forms: +
      +
    • Fortran-style packed 1-D array. +
    • C-style double-pointer, or list-of-rows. +
    • Epetra_SerialDenseMatrix object. +
    + In all cases, a "format" parameter specifies whether the data is laid out + in row-major or column-major order (i.e., whether coefficients for a row + lie contiguously or whether coefficients for a column lie contiguously). + See the documentation for the methods SumIntoGlobalValues() and + ReplaceGlobalValues(). + + Important notes: +
      +
    1. Since Epetra_FECrsMatrix inherits Epetra_CrsMatrix, the semantics of + the Insert/SumInto/Replace methods are the same as they are on + Epetra_CrsMatrix, which is: +
        +
      • InsertGlobalValues() inserts values into the matrix only if the graph + has not yet been finalized (FillComplete() has not yet been called). For + non-local values, the call to InsertGlobalValues() may succeed but the + GlobalAssemble() method may then fail because the non-local data is not + actually inserted in the underlying matrix until GlobalAssemble() is called. +
      • SumIntoGlobalValues() and ReplaceGlobalValues() only work for values + that already exist in the matrix. In other words, these methods can not be + used to put new values into the matrix. +
      +
    +*/ +class Epetra_FECrsMatrix : public Epetra_CrsMatrix { + public: + /** Constructor. */ + Epetra_FECrsMatrix(Epetra_DataAccess CV, + const Epetra_Map& RowMap, + int* NumEntriesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor. */ + Epetra_FECrsMatrix(Epetra_DataAccess CV, + const Epetra_Map& RowMap, + int NumEntriesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor. */ + Epetra_FECrsMatrix(Epetra_DataAccess CV, + const Epetra_Map& RowMap, + const Epetra_Map& ColMap, + int* NumEntriesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor. */ + Epetra_FECrsMatrix(Epetra_DataAccess CV, + const Epetra_Map& RowMap, + const Epetra_Map& ColMap, + int NumEntriesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor. */ + Epetra_FECrsMatrix(Epetra_DataAccess CV, + const Epetra_CrsGraph& Graph, + bool ignoreNonLocalEntries=false); + + /** Copy Constructor. */ + Epetra_FECrsMatrix(const Epetra_FECrsMatrix& src); + + /** Destructor. */ + virtual ~Epetra_FECrsMatrix(); + + /** Assignment operator */ + Epetra_FECrsMatrix& operator=(const Epetra_FECrsMatrix& src); + + enum { ROW_MAJOR = 0, COLUMN_MAJOR = 3 }; + + //Let the compiler know we intend to overload the following base-class + //functions, rather than hide them. + using Epetra_CrsMatrix::SumIntoGlobalValues; + using Epetra_CrsMatrix::InsertGlobalValues; + using Epetra_CrsMatrix::ReplaceGlobalValues; + + /** Sum a Fortran-style table (single-dimensional packed-list) of + coefficients into the matrix, adding them to any coefficients that + may already exist at the specified row/column locations. + + @param numIndices Number of rows (and columns) in the sub-matrix. + @param indices List of scatter-indices (rows and columns) for the + sub-matrix. + @param values List, length numIndices*numIndices. Square sub-matrix of + coefficients, packed in a 1-D array. Data is packed either contiguously + by row or by column, specified by the final parameter 'format'. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is COLUMN_MAJOR. + */ + int SumIntoGlobalValues(int numIndices, const int* indices, + const double* values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Sum a Fortran-style table (single-dimensional packed-list) of + coefficients into the matrix, adding them to any coefficients that + may already exist at the specified row/column locations. + + @param numRows Number of rows in the sub-matrix. + @param rows List of row-numbers (scatter-indices) for the sub-matrix. + @param numCols Number of columns in the sub-matrix. + @param cols List of column-numbers (scatter-indices) for the sub-matrix. + @param values List, length numRows*numCols. Rectangular sub-matrix of + coefficients, packed in a 1-D array. Data is packed either contiguously + by row or by column, specified by the final parameter 'format'. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is COLUMN_MAJOR. + */ + int SumIntoGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Sum C-style table (double-pointer, or list of lists) of coefficients + into the matrix, adding them to any coefficients that + may already exist at the specified row/column locations. + + @param numIndices Number of rows (and columns) in the sub-matrix. + @param indices List of scatter-indices (rows and columns) for the + sub-matrix. + @param values Square sub-matrix of coefficients, provided in a 2-D + array, or double-pointer. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is ROW_MAJOR. + */ + int SumIntoGlobalValues(int numIndices, const int* indices, + const double* const* values, + int format=Epetra_FECrsMatrix::ROW_MAJOR); + + /** Sum C-style table (double-pointer, or list of lists) of coefficients + into the matrix, adding them to any coefficients that + may already exist at the specified row/column locations. + + @param numRows Number of rows in the sub-matrix. + @param rows List of row-numbers (scatter-indices) for the sub-matrix. + @param numCols Number of columns in the sub-matrix. + @param cols List of column-numbers (scatter-indices) for the sub-matrix. + @param values Rectangular sub-matrix of coefficients, provided in a 2-D + array, or double-pointer. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is ROW_MAJOR. + */ + int SumIntoGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* const* values, + int format=Epetra_FECrsMatrix::ROW_MAJOR); + + /** Insert a Fortran-style table (single-dimensional packed-list) of + coefficients into the matrix. + + @param numIndices Number of rows (and columns) in the sub-matrix. + @param indices List of scatter-indices (rows and columns) for the + sub-matrix. + @param values List, length numIndices*numIndices. Square sub-matrix of + coefficients, packed in a 1-D array. Data is packed either contiguously + by row or by column, specified by the final parameter 'format'. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is COLUMN_MAJOR. + */ + int InsertGlobalValues(int numIndices, const int* indices, + const double* values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Insert a Fortran-style table (single-dimensional packed-list) of + coefficients into the matrix. + + @param numRows Number of rows in the sub-matrix. + @param rows List of row-numbers (scatter-indices) for the sub-matrix. + @param numCols Number of columns in the sub-matrix. + @param cols List of column-numbers (scatter-indices) for the sub-matrix. + @param values List, length numRows*numCols. Rectangular sub-matrix of + coefficients, packed in a 1-D array. Data is packed either contiguously + by row or by column, specified by the final parameter 'format'. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is COLUMN_MAJOR. + */ + int InsertGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Insert a C-style table (double-pointer, or list of lists) of coefficients + into the matrix. + + @param numIndices Number of rows (and columns) in the sub-matrix. + @param indices List of scatter-indices (rows and columns) for the + sub-matrix. + @param values Square sub-matrix of coefficients, provided in a 2-D + array, or double-pointer. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is ROW_MAJOR. + */ + int InsertGlobalValues(int numIndices, const int* indices, + const double* const* values, + int format=Epetra_FECrsMatrix::ROW_MAJOR); + + /** Insert a C-style table (double-pointer, or list of lists) of coefficients + into the matrix. + + @param numRows Number of rows in the sub-matrix. + @param rows List of row-numbers (scatter-indices) for the sub-matrix. + @param numCols Number of columns in the sub-matrix. + @param cols List of column-numbers (scatter-indices) for the sub-matrix. + @param values Rectangular sub-matrix of coefficients, provided in a 2-D + array, or double-pointer. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is ROW_MAJOR. + */ + int InsertGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* const* values, + int format=Epetra_FECrsMatrix::ROW_MAJOR); + + /** Copy a Fortran-style table (single-dimensional packed-list) of + coefficients into the matrix, replacing any coefficients that + may already exist at the specified row/column locations. + + @param numIndices Number of rows (and columns) in the sub-matrix. + @param indices List of scatter-indices (rows and columns) for the + sub-matrix. + @param values List, length numIndices*numIndices. Square sub-matrix of + coefficients, packed in a 1-D array. Data is packed either contiguously + by row or by column, specified by the final parameter 'format'. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is COLUMN_MAJOR. + */ + int ReplaceGlobalValues(int numIndices, const int* indices, + const double* values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Copy Fortran-style table (single-dimensional packed-list) of coefficients + into the matrix, replacing any coefficients that + may already exist at the specified row/column locations. + + @param numRows Number of rows in the sub-matrix. + @param rows List of row-numbers (scatter-indices) for the sub-matrix. + @param numCols Number of columns in the sub-matrix. + @param cols List, of column-numbers + (scatter-indices) for the sub-matrix. + @param values List, length numRows*numCols. Rectangular sub-matrix of + coefficients, packed in a 1-D array. Data is packed either contiguously + by row or by column, specified by the final parameter 'format'. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is COLUMN_MAJOR. + */ + int ReplaceGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Copy C-style table (double-pointer, or list of lists) of coefficients + into the matrix, replacing any coefficients that + may already exist at the specified row/column locations. + + @param numIndices Number of rows (and columns) in the sub-matrix. + @param indices List of scatter-indices (rows and columns) for the + sub-matrix. + @param values Square sub-matrix of coefficients, provided in a 2-D + array, or double-pointer. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is ROW_MAJOR. + */ + int ReplaceGlobalValues(int numIndices, const int* indices, + const double* const* values, + int format=Epetra_FECrsMatrix::ROW_MAJOR); + + /** Copy C-style table (double-pointer, or list of lists) of coefficients + into the matrix, replacing any coefficients that + may already exist at the specified row/column locations. + + @param numRows Number of rows in the sub-matrix. + @param rows List of row-numbers (scatter-indices) for the sub-matrix. + @param numCols Number of columns in the sub-matrix. + @param cols List of column-numbers (scatter-indices) for the sub-matrix. + @param values Rectangular sub-matrix of coefficients, provided in a 2-D + array, or double-pointer. + @param format Specifies whether the data in 'values' is packed in + column-major or row-major order. Valid values are + Epetra_FECrsMatrix::ROW_MAJOR or Epetra_FECrsMatrix::COLUMN_MAJOR. This + is an optional parameter, default value is ROW_MAJOR. + */ + int ReplaceGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* const* values, + int format=Epetra_FECrsMatrix::ROW_MAJOR); + + /** Sum a square structurally-symmetric sub-matrix into the global matrix. + For non-square sub-matrices, see the other overloading of this method. + + @param indices List of scatter-indices. indices.Length() must be the same + as values.M() and values.N(). + + @param values Sub-matrix of coefficients. Must be square. + + @param format Optional format specifier, defaults to COLUMN_MAJOR. + */ + int SumIntoGlobalValues(const Epetra_IntSerialDenseVector& indices, + const Epetra_SerialDenseMatrix& values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Sum a general sub-matrix into the global matrix. + For square structurally-symmetric sub-matrices, see the other + overloading of this method. + + @param rows List of row-indices. rows.Length() must be the same + as values.M(). + + @param cols List of column-indices. cols.Length() must be the same + as values.N(). + + @param values Sub-matrix of coefficients. + + @param format Optional format specifier, defaults to COLUMN_MAJOR. + */ + int SumIntoGlobalValues(const Epetra_IntSerialDenseVector& rows, + const Epetra_IntSerialDenseVector& cols, + const Epetra_SerialDenseMatrix& values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Insert a square structurally-symmetric sub-matrix into the global matrix. + For non-square sub-matrices, see the other overloading of this method. + + @param indices List of scatter-indices. indices.Length() must be the same + as values.M() and values.N(). + + @param values Sub-matrix of coefficients. Must be square. + + @param format Optional format specifier, defaults to COLUMN_MAJOR. + */ + int InsertGlobalValues(const Epetra_IntSerialDenseVector& indices, + const Epetra_SerialDenseMatrix& values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Insert a general sub-matrix into the global matrix. + For square structurally-symmetric sub-matrices, see the other + overloading of this method. + + @param rows List of row-indices. rows.Length() must be the same + as values.M(). + + @param cols List of column-indices. cols.Length() must be the same + as values.N(). + + @param values Sub-matrix of coefficients. + + @param format Optional format specifier, defaults to COLUMN_MAJOR. + */ + int InsertGlobalValues(const Epetra_IntSerialDenseVector& rows, + const Epetra_IntSerialDenseVector& cols, + const Epetra_SerialDenseMatrix& values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Use a square structurally-symmetric sub-matrix to replace existing + values in the global matrix. + For non-square sub-matrices, see the other overloading of this method. + + @param indices List of scatter-indices. indices.Length() must be the same + as values.M() and values.N(). + + @param values Sub-matrix of coefficients. Must be square. + + @param format Optional format specifier, defaults to COLUMN_MAJOR. + */ + int ReplaceGlobalValues(const Epetra_IntSerialDenseVector& indices, + const Epetra_SerialDenseMatrix& values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Use a general sub-matrix to replace existing values. + For square structurally-symmetric sub-matrices, see the other + overloading of this method. + + @param rows List of row-indices. rows.Length() must be the same + as values.M(). + + @param cols List of column-indices. cols.Length() must be the same + as values.N(). + + @param values Sub-matrix of coefficients. + + @param format Optional format specifier, defaults to COLUMN_MAJOR. + */ + int ReplaceGlobalValues(const Epetra_IntSerialDenseVector& rows, + const Epetra_IntSerialDenseVector& cols, + const Epetra_SerialDenseMatrix& values, + int format=Epetra_FECrsMatrix::COLUMN_MAJOR); + + /** Gather any overlapping/shared data into the non-overlapping partitioning + defined by the Map that was passed to this matrix at construction time. + Data imported from other processors is stored on the owning processor + with a "sumInto" or accumulate operation. + This is a collective method -- every processor must enter it before any + will complete it. + + ***NOTE***: When GlobalAssemble() calls FillComplete(), it passes the + arguments 'DomainMap()' and 'RangeMap()', which are the map attributes + held by the base-class CrsMatrix and its graph. If a rectangular matrix + is being assembled, the domain-map and range-map must be specified by + calling the other overloading of this method. Otherwise, GlobalAssemble() + has no way of knowing what these maps should really be. + + + @param callFillComplete option argument, defaults to true. + Determines whether GlobalAssemble() internally calls the + FillComplete() method on this matrix. + + @return error-code 0 if successful, non-zero if some error occurs + */ + int GlobalAssemble(bool callFillComplete=true); + + /** Gather any overlapping/shared data into the non-overlapping partitioning + defined by the Map that was passed to this matrix at construction time. + Data imported from other processors is stored on the owning processor + with a "sumInto" or accumulate operation. + This is a collective method -- every processor must enter it before any + will complete it. + + ***NOTE***: When GlobalAssemble() (the other overloading of this method) + calls FillComplete(), it passes the arguments 'DomainMap()' and + 'RangeMap()', which are the map attributes already held by the base-class + CrsMatrix and its graph. If a rectangular matrix is being assembled, the + domain-map and range-map must be specified. Otherwise, GlobalAssemble() + has no way of knowing what these maps should really be. + + + @param domain_map user-supplied domain map for this matrix + + @param range_map user-supplied range map for this matrix + + @param callFillComplete option argument, defaults to true. + Determines whether GlobalAssemble() internally calls the + FillComplete() method on this matrix. + + @return error-code 0 if successful, non-zero if some error occurs + */ + int GlobalAssemble(const Epetra_Map& domain_map, + const Epetra_Map& range_map, + bool callFillComplete=true); + + /** Set whether or not non-local data values should be ignored. By default, + non-local data values are NOT ignored. + */ + void setIgnoreNonLocalEntries(bool flag) { + ignoreNonLocalEntries_ = flag; + } + + private: + void DeleteMemory(); + + enum {SUMINTO = 0, REPLACE = 1, INSERT = 2}; + + int InputGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* const* values, + int format, + int mode); + + int InputGlobalValues(int numRows, const int* rows, + int numCols, const int* cols, + const double* values, + int format, + int mode); + + int InputNonlocalGlobalValues(int row, + int numCols, const int* cols, + const double* values, + int mode); + + int InsertNonlocalRow(int row, int offset); + + int InputNonlocalValue(int rowoffset, + int col, double value, + int mode); + + int myFirstRow_; + int myNumRows_; + + bool ignoreNonLocalEntries_; + + int numNonlocalRows_; + int* nonlocalRows_; + int* nonlocalRowLengths_; + int* nonlocalRowAllocLengths_; + int** nonlocalCols_; + double** nonlocalCoefs_; + + double* workData_; + int workDataLength_; +};//class Epetra_FECrsMatrix + +#endif /* EPETRA_FECRSMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_FEVbrMatrix.h b/fastlib/trilinos/include/Epetra_FEVbrMatrix.h new file mode 100644 index 0000000000..d8620d9566 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_FEVbrMatrix.h @@ -0,0 +1,276 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_FEVBRMATRIX_H +#define EPETRA_FEVBRMATRIX_H + +#include +#include + +/** Epetra Finite-Element VbrMatrix. This class provides the ability to + input finite-element style sub-matrix data, including sub-matrices with + non-local rows (which could correspond to shared finite-element nodes for + example). This class inherits Epetra_VbrMatrix, and so all Epetra_VbrMatrix + functionality is also available. +*/ + +class Epetra_FEVbrMatrix: public Epetra_VbrMatrix { + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_FEVbrMatrix constuctor with variable number of indices per row. + /*! Creates a Epetra_FEVbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - A Epetra_BlockMap listing the block rows that this processor + will contribute to. + \param In + NumBlockEntriesPerRow - An integer array of length NumRows + such that NumBlockEntriesPerRow[i] indicates the (approximate) + number of Block entries in the ith row. + */ + Epetra_FEVbrMatrix(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + int *NumBlockEntriesPerRow, + bool ignoreNonLocalEntries=false); + + //! Epetra_FEVbrMatrix constuctor with fixed number of indices per row. + /*! Creates a Epetra_FEVbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - An Epetra_BlockMap listing the block rows that this + processor will contribute to. + \param In + NumBlockEntriesPerRow - An integer that indicates the (approximate) + number of Block entries in the each Block row. + Note that it is possible to use 0 for this value and let fill occur + during the insertion phase. + */ + Epetra_FEVbrMatrix(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + int NumBlockEntriesPerRow, + bool ignoreNonLocalEntries=false); + + //! Epetra_FEVbrMatrix constuctor with variable number of indices per row. + /*! Creates a Epetra_FEVbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - A Epetra_BlockMap listing the block rows that this processor + will contribute to. + \param In + ColMap - A Epetra_BlockMap listing the block columns to be contained + on this processor. + \param In + NumBlockEntriesPerRow - An integer array of length NumRows + such that NumBlockEntriesPerRow[i] indicates the (approximate) + number of Block entries in the ith row. + */ + Epetra_FEVbrMatrix(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + const Epetra_BlockMap& ColMap, + int *NumBlockEntriesPerRow, + bool ignoreNonLocalEntries=false); + + //! Epetra_FEVbrMatrix constuctor with fixed number of indices per row. + /*! Creates a Epetra_FEVbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - An Epetra_BlockMap listing the block rows that this + processor will contribute to. + \param In + ColMap - An Epetra_BlockMap listing the block columns to be contained + on this processor. + \param In + NumBlockEntriesPerRow - An integer that indicates the (approximate) + number of Block entries in the each Block row. + Note that it is possible to use 0 for this value and let fill occur + during the insertion phase. + */ + Epetra_FEVbrMatrix(Epetra_DataAccess CV, + const Epetra_BlockMap& RowMap, + const Epetra_BlockMap& ColMap, + int NumBlockEntriesPerRow, + bool ignoreNonLocalEntries=false); + + /** Constructor with pre-constructed Graph. + */ + Epetra_FEVbrMatrix(Epetra_DataAccess CV, + const Epetra_CrsGraph& Graph, + bool ignoreNonLocalEntries=false); + + /** Copy Constructor. */ + Epetra_FEVbrMatrix(const Epetra_FEVbrMatrix& src); + + //! Epetra_VbrMatrix Destructor + virtual ~Epetra_FEVbrMatrix(); + //@} + + //! @name Insertion/Replace/SumInto methods + //@{ + + Epetra_FEVbrMatrix& operator=(const Epetra_FEVbrMatrix& src); + + //! Initialize all values in graph of the matrix with constant value. + /*! + \param In + ScalarConstant - Value to use. + + \return Integer error code, set to 0 if successful. + */ + int PutScalar(double ScalarConstant); + + //! Initiate insertion of a list of elements in a given global row of the matrix, values are inserted via SubmitEntry(). + /*! + \param In + BlockRow - Block Row number (in global coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginInsertGlobalValues(int BlockRow, int NumBlockEntries, int * BlockIndices); + + //! Initiate replacement of current values with this list of entries for a given global row of the matrix, values are replaced via SubmitEntry() + /*! + \param In + Row - Block Row number (in global coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginReplaceGlobalValues(int BlockRow, int NumBlockEntries, int *BlockIndices); + + //! Initiate summing into current values with this list of entries for a given global row of the matrix, values are replaced via SubmitEntry() + /*! + \param In + Row - Block Row number (in global coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginSumIntoGlobalValues(int BlockRow, int NumBlockEntries, int *BlockIndices); + + //Let the compiler know we intend to overload the base-class function + //SubmitBlockEntry rather than hide it. + using Epetra_VbrMatrix::SubmitBlockEntry; + + //! Submit a block entry to the indicated block row and column specified in the Begin routine. + /* Submit a block entry that will recorded in the block row that was initiated by one of the + Begin routines listed above. Once a one of the following routines: BeginInsertGlobalValues(), + BeginInsertMyValues(), BeginReplaceGlobalValues(), BeginReplaceMyValues(), BeginSumIntoGlobalValues(), + BeginSumIntoMyValues(), you \e must call SubmitBlockEntry() NumBlockEntries times to register the values + corresponding to the block indices passed in to the Begin routine. If the Epetra_VbrMatrix constuctor + was called in Copy mode, the values will be copied. However, no copying will be done until the EndSubmitEntries() + function is call to complete submission of the current block row. If the constructor was called in View mode, all + block entries passed via SubmitBlockEntry() will not be copied, but a pointer will be set to point to the argument Values + that was passed in by the user. + + For performance reasons, SubmitBlockEntry() does minimal processing of data. Any processing that can be + delayed is performed in EndSubmitEntries(). + + \param In + Values - The starting address of the values. + \param In + LDA - The stride between successive columns of Values. + \param In + NumRows - The number of rows passed in. + \param In + NumCols - The number of columns passed in. + + \return Integer error code, set to 0 if successful. + */ + int SubmitBlockEntry(double *Values, int LDA, int NumRows, int NumCols); + + //! Completes processing of all data passed in for the current block row. + /*! This function completes the processing of all block entries submitted via SubmitBlockEntry(). + It also checks to make sure that SubmitBlockEntry was called the correct number of times as + specified by the Begin routine that initiated the entry process. + */ + + int EndSubmitEntries(); + + int GlobalAssemble(bool callFillComplete=true); + + private: + int SetupForNonlocalSubmits(int BlockRow, + int NumBlockEntries, + int * BlockIndices, + bool IndicesAreLocal, + Epetra_CombineMode SubmitMode); + + int InputNonlocalBlockEntry(double *Values, int LDA, + int NumRows, int NumCols); + + int InsertNonlocalRow(int row, int offset, int numCols); + + void destroyNonlocalData(); + + bool ignoreNonLocalEntries_; + + int numNonlocalBlockRows_; + int* nonlocalBlockRows_; + int* nonlocalBlockRowLengths_; + int* nonlocalBlockRowAllocLengths_; + int** nonlocalBlockCols_; + + //Triple-pointers are gross, but we need one here. We want a 2-D table of + //pointer-to-matrix objects. If we only use a double-pointer, it would be + //too hard to change the lengths of the rows of the table. + + Epetra_SerialDenseMatrix*** nonlocalCoefs_; + + //Following the approach Mike uses in Epetra_VbrMatrix, we need some state + //variables to keep track of block-entry submits. + int curRowOffset_; + int curColOffset_; + int curNumCols_; + int* curCols_; + int curMode_; +}; + +#endif /* EPETRA_FEVBRMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_FEVector.h b/fastlib/trilinos/include/Epetra_FEVector.h new file mode 100644 index 0000000000..c749dcd066 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_FEVector.h @@ -0,0 +1,167 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_FEVECTOR_H +#define EPETRA_FEVECTOR_H + +#include +#include +#include +class Epetra_IntSerialDenseVector; +class Epetra_SerialDenseVector; + +/** Epetra Finite-Element Vector. This class inherits Epetra_MultiVector + and thus provides all Epetra_MultiVector functionality, with one + restriction: currently an Epetra_FEVector only has 1 internal vector. + + The added functionality provided by Epetra_FEVector is the ability to + perform finite-element style vector assembly. It accepts sub-vector + contributions, such as those that would come from element-load vectors, etc., + and these sub-vectors need not be wholly locally owned. In other words, the + user can assemble overlapping data (e.g., corresponding to shared + finite-element nodes). When the user is finished assembling their vector + data, they then call the method Epetra_FEVector::GlobalAssemble() which + gathers the overlapping data (all non-local data that was input on each + processor) into the data-distribution specified by the map that the + Epetra_FEVector is constructed with. + + Note: At the current time (Sept 6, 2002) the methods in this implementation + assume that there is only 1 point associated with each map element. This + limitation will be removed in the near future. +*/ + +class Epetra_FEVector : public Epetra_MultiVector { + public: + /** Constructor that requires a map specifying a non-overlapping + data layout. The methods SumIntoGlobalValues() and + ReplaceGlobalValues() will accept any global IDs, and GlobalAssemble() + will move any non-local data onto the appropriate owning processors. + */ + Epetra_FEVector(const Epetra_BlockMap& Map, + bool ignoreNonLocalEntries=false); + + /** Copy constructor. */ + Epetra_FEVector(const Epetra_FEVector& source); + + /** Destructor */ + virtual ~Epetra_FEVector(); + + /** Accumulate values into the vector, adding them to any values that + already exist for the specified indices. + */ + int SumIntoGlobalValues(int numIDs, const int* GIDs, const double* values); + + /** Accumulate values into the vector, adding them to any values that + already exist for the specified GIDs. + + @param GIDs List of global ids. Must be the same length as the + accompanying list of values. + + @param values List of coefficient values. Must be the same length as + the accompanying list of GIDs. + */ + int SumIntoGlobalValues(const Epetra_IntSerialDenseVector& GIDs, + const Epetra_SerialDenseVector& values); + + /** Copy values into the vector overwriting any values that already exist + for the specified indices. + */ + int ReplaceGlobalValues(int numIDs, const int* GIDs, const double* values); + + /** Copy values into the vector, replacing any values that + already exist for the specified GIDs. + + @param GIDs List of global ids. Must be the same length as the + accompanying list of values. + + @param values List of coefficient values. Must be the same length as + the accompanying list of GIDs. + */ + int ReplaceGlobalValues(const Epetra_IntSerialDenseVector& GIDs, + const Epetra_SerialDenseVector& values); + + int SumIntoGlobalValues(int numIDs, const int* GIDs, + const int* numValuesPerID, + const double* values); + + int ReplaceGlobalValues(int numIDs, const int* GIDs, + const int* numValuesPerID, + const double* values); + + /** Gather any overlapping/shared data into the non-overlapping partitioning + defined by the Map that was passed to this vector at construction time. + Data imported from other processors is stored on the owning processor + with a "sumInto" or accumulate operation. + This is a collective method -- every processor must enter it before any + will complete it. + */ + int GlobalAssemble(Epetra_CombineMode mode = Add); + + /** Set whether or not non-local data values should be ignored. + */ + void setIgnoreNonLocalEntries(bool flag) { + ignoreNonLocalEntries_ = flag; + } + + Epetra_FEVector& operator=(const Epetra_FEVector& source); + + private: + int inputValues(int numIDs, + const int* GIDs, const double* values, + bool accumulate); + + int inputValues(int numIDs, + const int* GIDs, const int* numValuesPerID, + const double* values, + bool accumulate); + + int inputNonlocalValue(int GID, double value, bool accumulate); + + int inputNonlocalValues(int GID, int numValues, const double* values, + bool accumulate); + + void destroyNonlocalData(); + + int myFirstID_; + int myNumIDs_; + double* myCoefs_; + + int* nonlocalIDs_; + int* nonlocalElementSize_; + int numNonlocalIDs_; + int allocatedNonlocalLength_; + double** nonlocalCoefs_; + + bool ignoreNonLocalEntries_; +}; + +#endif + diff --git a/fastlib/trilinos/include/Epetra_Flops.h b/fastlib/trilinos/include/Epetra_Flops.h new file mode 100644 index 0000000000..efbfa41c38 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Flops.h @@ -0,0 +1,94 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_FLOPS_H +#define EPETRA_FLOPS_H + +//! Epetra_Flops: The Epetra Floating Point Operations Class. +/*! The Epetra_Flops class provides basic support and consistent interfaces + for counting and reporting floating point operations performed in + the Epetra computational classes. All classes based on the Epetra_CompObject + can count flops by the user creating an Epetra_Flops object and calling the SetFlopCounter() + method for an Epetra_CompObject. + +*/ + +class Epetra_Flops { + + public: + //! Epetra_Flops Constructor. + /*! Creates a Epetra_Flops instance. This instance can be queried for + the number of floating point operations performed for the associated + \e this object. + */ + Epetra_Flops(void); + + //! Epetra_Flops Copy Constructor. + /*! Makes an exact copy of an existing Epetra_Flops instance. + */ + Epetra_Flops(const Epetra_Flops& Flops); + + //! Returns the number of floating point operations with \e this object and resets the count. + double Flops() const {double tmp = Flops_; Flops_ = 0.0; return(tmp);}; + + //! Resets the number of floating point operations to zero for \e this multi-vector. + void ResetFlops() {Flops_=0.0;}; + + //! Epetra_Flops Destructor. + /*! Completely deletes a Epetra_Flops object. + */ + virtual ~Epetra_Flops(void); + + Epetra_Flops& operator=(const Epetra_Flops& src) + { + Flops_ = src.Flops_; + return(*this); + } + + friend class Epetra_CompObject; + + protected: + mutable double Flops_; + //! Increment Flop count for \e this object from an int + void UpdateFlops(int Flops) const {Flops_ += (double) Flops;}; + //! Increment Flop count for \e this object from a long int + void UpdateFlops(long int Flops) const {Flops_ += (double) Flops;}; + //! Increment Flop count for \e this object from a double + void UpdateFlops(double Flops) const {Flops_ += Flops;}; + //! Increment Flop count for \e this object from a float + void UpdateFlops(float Flops) const {Flops_ +=(double) Flops;}; + + + private: + +}; + +#endif /* EPETRA_FLOPS_H */ diff --git a/fastlib/trilinos/include/Epetra_HashTable.h b/fastlib/trilinos/include/Epetra_HashTable.h new file mode 100644 index 0000000000..e117d23bf9 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_HashTable.h @@ -0,0 +1,131 @@ +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef Epetra_HashTable_H_ +#define Epetra_HashTable_H_ + +#include "Epetra_Object.h" + +class Epetra_HashTable : public Epetra_Object +{ + struct Node + { + int Key; + int Value; + Node * Ptr; + + Node( const int key = 0, const int value = 0, Node * ptr = 0 ) + : Key(key), Value(value), Ptr(ptr) {} + + private: + Node(const Node& src) + : Key(src.Key), Value(src.Value), Ptr(src.Ptr) {} + + Node& operator=(const Node& src) + { Key = src.Key; Value = src.Value; Ptr = src.Ptr; return(*this); } + }; + + Node ** Container_; + int Size_; + unsigned int Seed_; + + int Func( const int key ) { return (Seed_ ^ key)%Size_; } + + public: + + Epetra_HashTable( const int size, const unsigned int seed = (2654435761U) ) + : Container_(NULL), + Size_(size), + Seed_(seed) + { + if (size<=0) + throw ReportError( "Bad Hash Table Size: " + toString(size), -1 ); + + Container_ = new Node * [size]; + for( int i = 0; i < size; ++i ) Container_[i] = 0; + } + + Epetra_HashTable( const Epetra_HashTable & obj ) + : Container_(NULL), + Size_(obj.Size_), + Seed_(obj.Seed_) + { + Container_ = new Node * [Size_]; + for( int i = 0; i < Size_; ++i ) Container_[i] = 0; + for( int i = 0; i < Size_; ++i ) + { + Node * ptr = obj.Container_[i]; + while( ptr ) { Add( ptr->Key, ptr->Value ); ptr = ptr->Ptr; } + } + } + + ~Epetra_HashTable() + { + Node * ptr1; + Node * ptr2; + for( int i = 0; i < Size_; ++i ) + { + ptr1 = Container_[i]; + while( ptr1 ) { ptr2 = ptr1; ptr1 = ptr1->Ptr; delete ptr2; } + } + + delete [] Container_; + } + + void Add( const int key, const int value ) + { + int v = Func(key); + Node * n1 = Container_[v]; + Container_[v] = new Node(key,value,n1); + } + + int Get( const int key ) + { + Node * n = Container_[ Func(key) ]; + while( n && (n->Key != key) ) n = n->Ptr; + if( n ) return n->Value; + else return -1; + } + + private: + Epetra_HashTable& operator=(const Epetra_HashTable& src) + { + (void)src; + //not currently supported + bool throw_error = true; + if (throw_error) { + throw ReportError("Epetra_HashTable::operator= not supported.",-1); + } + return(*this); + } + +}; + +#endif diff --git a/fastlib/trilinos/include/Epetra_Import.h b/fastlib/trilinos/include/Epetra_Import.h new file mode 100644 index 0000000000..ed96986ac1 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Import.h @@ -0,0 +1,308 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_IMPORT_H +#define EPETRA_IMPORT_H + +#include "Epetra_Object.h" +#include "Epetra_BlockMap.h" +class Epetra_Distributor; + +//! Epetra_Import: This class builds an import object for efficient importing of off-processor elements. + +/*! Epetra_Import is used to construct a communication plan that can be called repeatedly by computational + classes such the Epetra matrix, vector and multivector classes to efficiently obtain off-processor + elements. + + This class currently has one constructor, taking two Epetra_Map or Epetra_BlockMap objects. + The first map specifies the global IDs of elements that we want to import later. The + second map specifies the global IDs that are owned by the calling processor. +*/ + +class Epetra_Import: public Epetra_Object { + + public: + + //! Constructs a Epetra_Import object from the source and target maps. + /*! This constructor builds an Epetra_Import object by comparing the GID lists of the source and + target maps. + \param TargetMap (In) Map containing the GIDs from which data should be imported to each processor from + the source map whenever an import operation is performed using this importer. + \param SourceMap (In) Map containing the GIDs that should be used for importing data. + + \warning Note that the SourceMap \e must have GIDs uniquely owned, each GID of the source map can occur only once. + + + Builds an import object that will transfer objects built with SourceMap to objects built with TargetMap. + + A Epetra_Import object categorizes the elements of the target map into three sets as follows: +
      +
    1. All elements in the target map that have the same GID as the corresponding element of the source map, + starting with the first + element in the target map, going up to the first element that is different from the source map. The number of + these IDs is returned by NumSameIDs(). +
    2. All elements that are local to the processor, but are not part of the first set of elements. These elements + have GIDs that are owned by the calling processor, but at least the first element of this list is permuted. + Even if subsequent elements are not permuted, they are included in this list. The number of permuted elements + is returned by NumPermutedIDs(). The list of elements (local IDs) in the source map that are permuted can be + found in the list PermuteFromLIDs(). The list of elements (local IDs) in the target map that are the new locations + of the source elements can be found in the list PermuteToLIDs(). +
    3. All remaining elements of the target map correspond to global IDs that are owned by remote processors. The number + of these elements is returned by NumRemoteIDs() and the list of these is returned by RemoteLIDs(). +
    + +Given the above information, the Epetra_Import constructor builds a list of elements that must be communicated to other +processors as a result of import requests. The number of exported elements (where multiple sends of the same element +to different processors is counted) is returned by NumExportIDs(). The local IDs to be sent are returned by the list +ExportLIDs(). The processors to which each of the elements will be sent in returned in a list of the same length by +ExportPIDs(). + +The total number of elements that will be sent by the calling processor is returned by NumSend(). The total number of +elements that will be received is returned by NumRecv(). + + +The following example illustrates the basic concepts. + +Assume we have 3 processors and 9 global elements with each processor owning 3 elements as follows +\verbatim + PE 0 Elements | PE 1 Elements | PE 2 Elements + 0 1 2 3 4 5 6 7 8 +\endverbatim + +The above layout essentially defines the source map argument of the import object. + +This could correspond to a 9 by 9 matrix with the first three rows on PE 0, and so on. Suppose that this matrix +is periodic tridiagonal having the following sparsity pattern: + +\verbatim + +PE 0 Rows: + + X X 0 0 0 0 0 0 X + X X X 0 0 0 0 0 0 + 0 X X X 0 0 0 0 0 + +PE 1 Rows: + + 0 0 X X X 0 0 0 0 + 0 0 0 X X X 0 0 0 + 0 0 0 0 X X X 0 0 + +PE 2 Rows: + + 0 0 0 0 0 X X X 0 + 0 0 0 0 0 0 X X X + X 0 0 0 0 0 0 X X + +\endverbatim + +To perform a matrix vector multiplication operation y = A*x (assuming that x has the same distribution as the +rows of the matrix A) each processor will need to import elements of x that +are not local. To do this, we build a target map on each processor as follows: +\verbatim + PE 0 Elements | PE 1 Elements | PE 2 Elements + 0 1 2 3 8 2 3 4 5 6 0 5 6 7 8 +\endverbatim + +The above list is the elements that will be needed to perform the matrix vector multiplication locally on each processor. +Note that the ordering of the elements on each processor is not unique, but has been chosen for illustration. + +With these two maps passed into the Epetra_Import constructor, we get the following attribute definitions: + +On PE 0: + +\verbatim +NumSameIDs = 3 + +NumPermuteIDs = 0 +PermuteToLIDs = 0 +PermuteFromLIDs = 0 + +NumRemoteIDs = 2 +RemoteLIDs = [3, 4] + +NumExportIDs = 2 +ExportLIDs = [0, 2] +ExportPIDs = [1, 2] + +NumSend = 2 +NumRecv = 2 + +\endverbatim + +On PE 1: + +\verbatim +NumSameIDs = 0 + +NumPermuteIDs = 3 +PermuteToLIDs = [0, 1, 2] +PermuteFromLIDs = [1, 2, 3] + +NumRemoteIDs = 2 +RemoteLIDs = [0, 4] + +NumExportIDs = 2 +ExportLIDs = [0, 2] +ExportPIDs = [0, 2] + +NumSend = 2 +NumRecv = 2 + +\endverbatim + +On PE 2: + +\verbatim +NumSameIDs = 0 + +NumPermuteIDs = 3 +PermuteToLIDs = [0, 1, 2] +PermuteFromLIDs = [2, 3, 4] + +NumRemoteIDs = 2 +RemoteLIDs = [0, 1] + +NumExportIDs = 2 +ExportLIDs = [0, 2] +ExportPIDs = [0, 1] + +NumSend = 2 +NumRecv = 2 + +\endverbatim + + + Using Epetra_Import Objects + +Once a Epetra_Import object has been constructed, it can be used by any of the Epetra classes that support distributed global +objects, namely Epetra_Vector, Epetra_MultiVector, Epetra_CrsGraph, Epetra_CrsMatrix and Epetra_VbrMatrix. +All of these classes have Import and Export methods that will fill new objects whose distribution is described by +the target map, taking elements from the source object whose distribution is described by the source map. Details of usage +for each class is given in the appropriate class documentation. + +Note that the reverse operation, an export, using this importer is also possible and appropriate in some instances. +For example, if we compute y = A^Tx, the transpose matrix-multiplication operation, then we can use the importer we constructed +in the above example to do an export operation to y, adding the contributions that come from multiple processors. + + */ + + Epetra_Import( const Epetra_BlockMap & TargetMap, const Epetra_BlockMap & SourceMap ); + + //! Epetra_Import copy constructor. + Epetra_Import(const Epetra_Import& Importer); + + //! Epetra_Import destructor. + + virtual ~Epetra_Import(void); + //! Returns the number of elements that are identical between the source and target maps, up to the first different ID + int NumSameIDs() const {return(NumSameIDs_);}; + + //! Returns the number of elements that are local to the calling processor, but not part of the first NumSameIDs() elements. + int NumPermuteIDs() const {return(NumPermuteIDs_);}; + + //! List of elements in the source map that are permuted. + int * PermuteFromLIDs () const {return(PermuteFromLIDs_);}; + //! List of elements in the target map that are permuted. + int * PermuteToLIDs () const {return(PermuteToLIDs_);}; + + //! Returns the number of elements that are not on the calling processor. + int NumRemoteIDs() const {return(NumRemoteIDs_);}; + + //! List of elements in the target map that are coming from other processors. + int * RemoteLIDs() const {return(RemoteLIDs_);}; + + //! Returns the number of elements that must be sent by the calling processor to other processors. + int NumExportIDs () const {return(NumExportIDs_);}; + + //! List of elements that will be sent to other processors. + int * ExportLIDs () const {return(ExportLIDs_);}; + + //! List of processors to which elements will be sent, ExportLIDs() [i] will be sent to processor ExportPIDs() [i]. + int * ExportPIDs () const {return(ExportPIDs_);}; + + //! Total number of elements to be sent. + int NumSend() const {return(NumSend_);}; + + //! Total number of elements to be received. + int NumRecv() const {return(NumRecv_);}; + + //! Returns the SourceMap used to construct this importer + const Epetra_BlockMap & SourceMap() const {return(SourceMap_);}; + + //! Returns the TargetMap used to construct this importer + const Epetra_BlockMap & TargetMap() const {return(TargetMap_);}; + + Epetra_Distributor & Distributor() const {return(*Distor_);}; + + //! @name Print object to an output stream + //@{ + virtual void Print(ostream & os) const; + //@} + protected: + + friend class Epetra_BlockMap; + + private: + Epetra_Import& operator=(const Epetra_Import& src) + { + (void)src; + //not currently supported + bool throw_error = true; + if (throw_error) { + throw ReportError("Epetra_Import::operator= not supported.",-1); + } + return(*this); + } + + Epetra_BlockMap TargetMap_; + Epetra_BlockMap SourceMap_; + + int NumSameIDs_; + int NumPermuteIDs_; + int * PermuteToLIDs_; + int * PermuteFromLIDs_; + int NumRemoteIDs_; + int * RemoteLIDs_; + + int NumExportIDs_; + int * ExportLIDs_; + int * ExportPIDs_; + + int NumSend_; + int NumRecv_; + + Epetra_Distributor * Distor_; + + +}; + +#endif /* EPETRA_IMPORT_H */ diff --git a/fastlib/trilinos/include/Epetra_IntSerialDenseMatrix.h b/fastlib/trilinos/include/Epetra_IntSerialDenseMatrix.h new file mode 100644 index 0000000000..ef1d811781 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_IntSerialDenseMatrix.h @@ -0,0 +1,395 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_INTSERIALDENSEMATRIX_H +#define EPETRA_INTSERIALDENSEMATRIX_H + +#include "Epetra_Object.h" + +//! Epetra_IntSerialDenseMatrix: A class for constructing and using general dense integer matrices. + +/*! The Epetra_IntSerialDenseMatrix class enables the construction and use of integer-valued, general + dense matrices. + +The Epetra_IntSerialDenseMatrix class is intended to provide very basic support for dense rectangular matrices. + + +Constructing Epetra_IntSerialDenseMatrix Objects + +There are four Epetra_IntSerialDenseMatrix constructors. The first constructs a zero-sized object which should be made +to appropriate length using the Shape() or Reshape() functions and then filled with the [] or () operators. +The second constructs an object sized to the dimensions specified, which should be filled with the [] or () operators. +The third is a constructor that accepts user +data as a 2D array, and the fourth is a copy constructor. The third constructor has +two data access modes (specified by the Epetra_DataAccess argument): +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the object. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +Epetra_IntSerialDenseMatrix constructors will throw an exception if an error occurrs. +These exceptions will alway be negative integer values as follows: +
      +
    1. -1 Invalid dimension specified. +
    2. -2 Shape returned non-zero. +
    3. -3 Null pointer specified for user's data. +
    4. -99 Internal Epetra_IntSerialDenseMatrix error. Contact developer. +
    + +Other Epetra_IntSerialDenseMatrix functions that do not return an integer error code +(such as operators () and [] ) will throw an exception if an error occurrs. +These exceptions will be integer values as follows: +
      +
    1. -1 Invalid row specified. +
    2. -2 Invalid column specified. +
    3. -5 Invalid assignment (type mismatch). +
    4. -99 Internal Epetra_IntSerialDenseMatrix error. Contact developer. +
    + + +bExtracting Data from Epetra_IntSerialDenseMatrix Objects + +Once a Epetra_IntSerialDenseMatrix is constructed, it is possible to view the data via access functions. + +\warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective. + + +Vector and Utility Functions + +Once a Epetra_IntSerialDenseMatrix is constructed, several mathematical functions can be applied to +the object. Specifically: +
      +
    • Multiplication. +
    • Norms. +
    + + +*/ + + +//========================================================================= +class Epetra_IntSerialDenseMatrix : public Epetra_Object { + + public: + + //! @name Constructor/Destructor Methods + //@{ + //! Default constructor; defines a zero size object. + /*! + Epetra_IntSerialDenseMatrix objects defined by the default constructor should be sized with the + Shape() or Reshape functions. + Values should be defined by using the [] or () operators. + */ + Epetra_IntSerialDenseMatrix(); + + //! Shaped constructor; defines a variable-sized object + /*! + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + Epetra_SerialDenseMatrix objects defined by the shaped constructor are already shaped to the + dimensions given as a parameters. All values are initialized to 0. Calling this constructor + is equivalent to using the default constructor, and then calling the Shape function on it. + Values should be defined by using the [] or () operators. + */ + Epetra_IntSerialDenseMatrix(int NumRows, int NumCols); + + //! Set object values from two-dimensional array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + A - Pointer to an array of integer numbers. The first vector starts at A. + The second vector starts at A+LDA, the third at A+2*LDA, and so on. + \param In + LDA - The "Leading Dimension", or stride between vectors in memory. + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + See Detailed Description section for further discussion. + */ + Epetra_IntSerialDenseMatrix(Epetra_DataAccess CV, int* A, int LDA, int NumRows, int NumCols); + + //! Epetra_IntSerialDenseMatrix copy constructor. + /*! + This matrix will take on the data access mode of the Source matrix. + */ + Epetra_IntSerialDenseMatrix(const Epetra_IntSerialDenseMatrix& Source); + + //! Epetra_IntSerialDenseMatrix destructor. + virtual ~Epetra_IntSerialDenseMatrix (); + //@} + + //! @name Shaping/sizing Methods + //@{ + //! Set dimensions of a Epetra_IntSerialDenseMatrix object; init values to zero. + /*! + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + Allows user to define the dimensions of a Epetra_IntSerialDenseMatrix at any point. This function can + be called at any point after construction. Any values that were previously in this object are + destroyed and the resized matrix starts off with all zero values. + + \return Integer error code, set to 0 if successful. + */ + int Shape(int NumRows, int NumCols); + + //! Reshape a Epetra_IntSerialDenseMatrix object. + /*! + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + Allows user to define the dimensions of a Epetra_IntSerialDenseMatrix at any point. This function can + be called at any point after construction. Any values that were previously in this object are + copied into the new shape. If the new shape is smaller than the original, the upper left portion + of the original matrix (the principal submatrix) is copied to the new matrix. + + \return Integer error code, set to 0 if successful. + */ + int Reshape(int NumRows, int NumCols); + //@} + + //! @name Data Accessor methods + //@{ + + //! Computes the 1-Norm of the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. + */ + virtual int OneNorm(); + + //! Computes the Infinity-Norm of the \e this matrix. + virtual int InfNorm(); + + //! Copy from one matrix to another. + /*! + The operator= allows one to copy the values from one existing IntSerialDenseMatrix to another. + The left hand side matrix will take on the data access mode of the right hand side matrix. + + \return Values of the left hand side matrix are modified by the values of the right hand side matrix. + */ + Epetra_IntSerialDenseMatrix& operator = (const Epetra_IntSerialDenseMatrix& Source); + + //! Comparison operator. + /*! operator== compares two Epetra_IntSerialDenseMatrix objects, returns false if sizes are different, + or if any coefficients differ. + */ + bool operator==(const Epetra_IntSerialDenseMatrix& rhs) const; + + //! Inequality operator + /*! operator!= simply returns the negation of operator==. + */ + bool operator!=(const Epetra_IntSerialDenseMatrix& rhs) const + { return !(*this == rhs); } + + //! Element access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Element from the specified row and column. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + int& operator () (int RowIndex, int ColIndex); + + //! Element access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Element from the specified row and column. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const int& operator () (int RowIndex, int ColIndex) const; + + //! Column access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Pointer to address of specified column. + + \warning No bounds checking can be done for the index i in the expression A[j][i]. + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + int* operator [] (int ColIndex); + + //! Column access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Pointer to address of specified column. + + \warning No bounds checking can be done for the index i in the expression A[j][i]. + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const int* operator [] (int ColIndex) const; + + //! Set matrix values to random numbers. + /*! + IntSerialDenseMatrix uses the random number generator provided by Epetra_Util. + The matrix values will be set to random values on the interval (0, 2^31 - 1). + + \return Integer error code, set to 0 if successful. + */ + int Random(); + + //! Returns row dimension of system. + int M() const {return(M_);}; + + //! Returns column dimension of system. + int N() const {return(N_);}; + + //! Returns const pointer to the \e this matrix. + const int* A() const {return(A_);}; + + //! Returns pointer to the \e this matrix. + int* A() {return(A_);}; + + //! Returns the leading dimension of the \e this matrix. + int LDA() const {return(LDA_);}; + + //! Returns the data access mode of the \e this matrix. + Epetra_DataAccess CV() const {return(CV_);}; + //@} + + //! @name I/O methods + //@{ + //! Print service methods; defines behavior of ostream << operator. + virtual void Print(ostream& os) const; + //@} + + //! @name Expert-only unsupported methods + //@{ + + //! Reset an existing IntSerialDenseMatrix to point to another Matrix. + /*! Allows an existing IntSerialDenseMatrix to become a View of another + matrix's data, regardless of the DataAccess mode of the Source matrix. + It is assumed that the Source matrix is an independent matrix, and + no checking is done to verify this. + + This is used by Epetra_CrsGraph in the OptimizeStorage method. It is used so that + an existing (Copy) matrix can be converted to a View. This frees up + memory that CrsGraph no longer needs. + + @param Source The IntSerialDenseMatrix this will become a view of. + + \return Integer error code, set to 0 if successful, and set to -1 + if a type mismatch occured. + + \warning This method is extremely dangerous and should only be used by experts. + */ + + int MakeViewOf(const Epetra_IntSerialDenseMatrix& Source); + //@} + + protected: + + void CopyMat(int* Source, int Source_LDA, int NumRows, int NumCols, int* Target, int Target_LDA); + void CleanupData(); + + Epetra_DataAccess CV_; + bool A_Copied_; + int M_; + int N_; + int LDA_; + int* A_; + +}; + +// inlined definitions of op() and op[] +//========================================================================= +inline int& Epetra_IntSerialDenseMatrix::operator () (int RowIndex, int ColIndex) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(RowIndex >= M_ || RowIndex < 0) + throw ReportError("Row index = " + toString(RowIndex) + + " Out of Range 0 - " + toString(M_-1),-1); + if(ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " + toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_[ColIndex*LDA_ + RowIndex]); +} +//========================================================================= +inline const int& Epetra_IntSerialDenseMatrix::operator () (int RowIndex, int ColIndex) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(RowIndex >= M_ || RowIndex < 0) + throw ReportError("Row index = " + toString(RowIndex) + + " Out of Range 0 - " + toString(M_-1),-1); + if(ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " + toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_[ColIndex * LDA_ + RowIndex]); +} +//========================================================================= +inline int* Epetra_IntSerialDenseMatrix::operator [] (int ColIndex) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " + toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_+ ColIndex * LDA_); +} +//========================================================================= +inline const int* Epetra_IntSerialDenseMatrix::operator [] (int ColIndex) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " + toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_ + ColIndex * LDA_); +} +//========================================================================= + +#endif /* EPETRA_INTSERIALDENSEMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_IntSerialDenseVector.h b/fastlib/trilinos/include/Epetra_IntSerialDenseVector.h new file mode 100644 index 0000000000..3dd0c7f099 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_IntSerialDenseVector.h @@ -0,0 +1,289 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_INTSERIALDENSEVECTOR_H +#define EPETRA_INTSERIALDENSEVECTOR_H + +#include "Epetra_Object.h" +#include "Epetra_IntSerialDenseMatrix.h" + +//! Epetra_IntSerialDenseVector: A class for constructing and using dense vectors. + +/*! The Epetra_IntSerialDenseVector class enables the construction and use of integer-valued, + dense vectors. It derives from the Epetra_IntSerialDenseMatrix class. + +The Epetra_IntSerialDenseVector class is intended to provide convenient vector notation but derives all signficant +functionality from Epetra_IntSerialDenseMatrix. + +Constructing Epetra_IntSerialDenseVector Objects + +There are three Epetra_IntSerialDenseVector constructors. The first constructs a zero-length object which should be made +to appropriate length using the Size() or Resize() functions and then filled with the [] or () operators. +The second constructs an object sized to the dimension specified, which should be filled with the [] or () operators. +The third is a constructor that accepts user +data as a 1D array, and the fourth is a copy constructor. The third constructor has +two data access modes (specified by the Epetra_DataAccess argument): +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the object. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +Extracting Data from Epetra_IntSerialDenseVector Objects + +Once a Epetra_IntSerialDenseVector is constructed, it is possible to view the data via access functions. + +\warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective. + +*/ + + +//========================================================================= +class Epetra_IntSerialDenseVector : public Epetra_IntSerialDenseMatrix{ + + public: + + //! Default constructor; defines a zero size object. + /*! + Epetra_IntSerialDenseVector objects defined by the default constructor should be sized with the + Size() or Resize functions. + Values should be defined by using the [] or () operators. + */ + Epetra_IntSerialDenseVector(); + + //! Sized constructor; defines a variable-sized object + /*! + \param In + Length - Length of vector. + + Epetra_IntSerialDenseVector objects defined by the sized constructor are already sized to the + dimension given as a parameter. All values are initialized to 0. Calling this constructor + is equivalent to using the default constructor, and then calling the Size function on it. + Values should be defined by using the [] or () operators. + */ + Epetra_IntSerialDenseVector(int Length); + + //! Set object values from one-dimensional array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Values - Pointer to an array of integer numbers containing the values. + \param In + Length - Length of vector. + + See Detailed Description section for further discussion. + */ + Epetra_IntSerialDenseVector(Epetra_DataAccess CV, int* Values, int Length); + + //! Epetra_IntSerialDenseVector copy constructor. + + Epetra_IntSerialDenseVector(const Epetra_IntSerialDenseVector& Source); + + //! Set length of a Epetra_IntSerialDenseVector object; init values to zero. + /*! + \param In + Length - Length of vector object. + + Allows user to define the dimension of a Epetra_IntSerialDenseVector. This function can + be called at any point after construction. Any values that were previously in this object are + destroyed and the resized vector starts off with all zero values. + + \return Integer error code, set to 0 if successful. + */ + int Size(int Length) {return(Epetra_IntSerialDenseMatrix::Shape(Length, 1));}; + + //! Resize a Epetra_IntSerialDenseVector object. + /*! + \param In + Length - Length of vector object. + + Allows user to define the dimension of a Epetra_IntSerialDenseVector. This function can + be called at any point after construction. Any values that were previously in this object are + copied into the new size. If the new shape is smaller than the original, the first Length values + are copied to the new vector. + + \return Integer error code, set to 0 if successful. + */ + int Resize(int Length) {return(Epetra_IntSerialDenseMatrix::Reshape(Length, 1));}; + + //! Epetra_IntSerialDenseVector destructor. + virtual ~Epetra_IntSerialDenseVector (); + + //bring the base-class operator() into the current scope, in order to tell the + //compiler that we intend to overload it, rather than hide it. + using Epetra_IntSerialDenseMatrix::operator(); + + //! Element access function. + /*! + Returns the specified element of the vector. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + int& operator () (int Index); + + //! Element access function. + /*! + Returns the specified element of the vector. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const int& operator () (int Index) const; + + //! Element access function. + /*! + Returns the specified element of the vector. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + int& operator [] (int Index); + + //! Element access function. + /*! + Returns the specified element of the vector. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const int& operator [] (int Index) const; + + //! Set vector values to random numbers. + /*! + IntSerialDenseVector uses the random number generator provided by Epetra_Util. + The vector values will be set to random values on the interval (0, 2^31 - 1). + + \return Integer error code, set to 0 if successful. + */ + int Random(); + + //! Returns length of vector. + int Length() const {return(M_);}; + + //! Returns pointer to the values in vector. + int* Values() {return(A_);}; + + //! Returns const pointer to the values in vector. + const int* Values() const {return(A_);}; + + //! Returns the data access mode of the \e this vector. + Epetra_DataAccess CV() const {return(CV_);}; + + //! Copy from one vector to another. + /*! + The operator= allows one to copy the values from one existing IntSerialDenseVector to another. + The left hand side vector will take on the data access mode of the right hand side vector. + + \return Values of the left hand side vector are modified by the values of the right hand side vector. + */ + Epetra_IntSerialDenseVector& operator = (const Epetra_IntSerialDenseVector& Source); + + //! @name I/O methods + //@{ + //! Print service methods; defines behavior of ostream << operator. + virtual void Print(ostream& os) const; + //@} + + //! @name Expert-only unsupported methods + //@{ + + //Bring the base-class MakeViewOf method into the current scope so that the + //compiler knows we intend to overload it, rather than hide it. + using Epetra_IntSerialDenseMatrix::MakeViewOf; + + //! Reset an existing IntSerialDenseVector to point to another Vector. + /*! Allows an existing IntSerialDenseVector to become a View of another + vector's data, regardless of the DataAccess mode of the Source vector. + It is assumed that the Source vector is an independent vector, and + no checking is done to verify this. + + This is used by Epetra_CrsGraph in the OptimizeStorage method. It is used + so that an existing (Copy) vector can be converted to a View. This frees up + memory that CrsGraph no longer needs. + + @param Source The IntSerialDenseVector this will become a view of. + + \return Integer error code, set to 0 if successful. + + \warning This method is extremely dangerous and should only be used by experts. + */ + + int MakeViewOf(const Epetra_IntSerialDenseVector& Source); + //@} +}; + +// inlined definitions of op() and op[] +//========================================================================= +inline int& Epetra_IntSerialDenseVector::operator() (int Index) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(Index >= M_ || Index < 0) + throw ReportError("Index = " + toString(Index) + + " Out of Range 0 - " + toString(M_-1),-1); +#endif + return(A_[Index]); +} +//========================================================================= +inline const int& Epetra_IntSerialDenseVector::operator() (int Index) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(Index >= M_ || Index < 0) + throw ReportError("Index = " + toString(Index) + + " Out of Range 0 - " + toString(M_-1),-1); +#endif + return(A_[Index]); +} +//========================================================================= +inline int& Epetra_IntSerialDenseVector::operator [] (int Index) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(Index >= M_ || Index < 0) + throw ReportError("Index = " + toString(Index) + + " Out of Range 0 - " + toString(M_-1),-1); +#endif + return(A_[Index]); +} +//========================================================================= +inline const int& Epetra_IntSerialDenseVector::operator [] (int Index) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if(Index >= M_ || Index < 0) + throw ReportError("Index = " + toString(Index) + + " Out of Range 0 - " + toString(M_-1),-1); +#endif + return(A_[Index]); +} +//========================================================================= + +#endif /* EPETRA_INTSERIALDENSEVECTOR_H */ diff --git a/fastlib/trilinos/include/Epetra_IntVector.h b/fastlib/trilinos/include/Epetra_IntVector.h new file mode 100644 index 0000000000..9fd58ea1bf --- /dev/null +++ b/fastlib/trilinos/include/Epetra_IntVector.h @@ -0,0 +1,291 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_INTVECTOR_H +#define EPETRA_INTVECTOR_H + +#include "Epetra_DistObject.h" +#include "Epetra_BlockMap.h" +#include "Epetra_Distributor.h" +class Epetra_Map; + +//! Epetra_IntVector: A class for constructing and using dense integer vectors on a parallel computer. + +/*! The Epetra_IntVector class enables the construction and use of integer + dense vectors in a distributed memory environment. The distribution of the dense + vector is determined in part by a Epetra_Comm object and a Epetra_Map (or Epetra_LocalMap + or Epetra_BlockMap). + + + Distributed Global vs. Replicated Local +
      +
    • Distributed Global Vectors - In most instances, a multi-vector will be partitioned + across multiple memory images associated with multiple processors. In this case, there is + a unique copy of each element and elements are spread across all processors specified by + the Epetra_Comm communicator. +
    • Replicated Local Vectors - Some algorithms use vectors that are too small to + be distributed across all processors. Replicated local vectors handle + these types of situation. +
    + +Constructing Epetra_IntVectors + +There are four Epetra_IntVector constructors. The first is a basic constructor that allocates +space and sets all values to zero, the second is a +copy constructor. The third and fourth constructors work with user data. These constructors have +two data access modes: +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the vector. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +All Epetra_IntVector constructors require a map argument that describes the layout of elements +on the parallel machine. Specifically, +\c map is a Epetra_Map, Epetra_LocalMap or Epetra_BlockMap object describing the desired +memory layout for the vector. + +There are four different Epetra_IntVector constructors: +
      +
    • Basic - All values are zero. +
    • Copy - Copy an existing vector. +
    • Copy from or make view of user int array. +
    + +Extracting Data from Epetra_IntVectors + +Once a Epetra_IntVector is constructed, it is possible to extract a copy of the values or create +a view of them. + +\warning ExtractView functions are \e extremely dangerous from a data hiding perspective. +For both ExtractView fuctions, there is a corresponding ExtractCopy function. We +strongly encourage users to develop code using ExtractCopy functions first and +only use the ExtractView functions in a secondary optimization phase. + +There are two Extract functions: +
      +
    • ExtractCopy - Copy values into a user-provided array. +
    • ExtractView - Set user-provided array to point to Epetra_IntVector data. +
    + + +\warning A Epetra_Map, Epetra_LocalMap or Epetra_BlockMap object is required for all + Epetra_IntVector constructors. + +*/ + +//========================================================================= +class Epetra_IntVector : public Epetra_DistObject { + + public: + + //! @name Constructors/destructors + //@{ + //! Basic Epetra_IntVector constuctor. + /*! Creates a Epetra_IntVector object and, by default, fills with zero values. + + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + + \warning Note that, because Epetra_LocalMap + derives from Epetra_Map and Epetra_Map derives from Epetra_BlockMap, this constructor works + for all three types of Epetra map classes. + \param In + zeroOut - If true then the allocated memory will be zeroed + out initialy. If false then this memory will not + be touched which can be significantly faster. + + \return Pointer to a Epetra_IntVector. + + */ + Epetra_IntVector(const Epetra_BlockMap& Map, bool zeroOut = true); + + //! Epetra_IntVector copy constructor. + + Epetra_IntVector(const Epetra_IntVector& Source); + + //! Set vector values from user array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + \param In + V - Pointer to an array of integer numbers.. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_IntVector(Epetra_DataAccess CV, const Epetra_BlockMap& Map, int *V); + + //! Epetra_IntVector destructor. + virtual ~Epetra_IntVector (); + //@} + + + //! @name Post-construction modification methods + //@{ + //! Set all elements of the vector to Value + int PutValue(int Value); + //@} + + + //! @name Extraction methods + //@{ + + + //! Put vector values into user-provided array. + /*! + \param Out + V - Pointer to memory space that will contain the vector values. + + \return Integer error code, set to 0 if successful. + */ + int ExtractCopy(int *V) const; + + //! Set user-provided address of V. + /*! + \param Out + V - Address of a pointer to that will be set to point to the values of the vector. + + \return Integer error code, set to 0 if successful. + */ + int ExtractView(int **V) const; + //@} + + //! @name Mathematical methods + //@{ + //! Find maximum value + /*! + \return Maximum value across all processors. + */ + int MaxValue(); + + //! Find minimum value + /*! + \return Minimum value across all processors. + */ + int MinValue(); + + //@} + + //! @name Overloaded operators + //@{ + + //! = Operator. + /*! + \param In + A - Epetra_IntVector to copy. + + \return Epetra_IntVector. + */ + Epetra_IntVector& operator = (const Epetra_IntVector& Source); + + //! Element access function. + /*! + \return V[Index]. + */ + int& operator [] (int index) { return Values_[index]; } + //! Element access function. + /*! + \return V[Index]. + */ + const int& operator [] (int index) const { return Values_[index]; } + //@} + + //! @name Attribute access functions + //@{ + + //! Returns a pointer to an array containing the values of this vector. + int * Values() const {return(Values_);}; + + //! Returns the local vector length on the calling processor of vectors in the multi-vector. + int MyLength() const {return(Map().NumMyPoints());}; + + //! Returns the global vector length of vectors in the multi-vector. + int GlobalLength() const {return(Map().NumGlobalPoints());}; + //@} + + //! @name I/O methods + //@{ + + //! Print method + virtual void Print(ostream & os) const; + //@} + private: + + int AllocateForCopy(); + int DoCopy(int * V); + int AllocateForView(); + int DoView(int * V); + + // Routines to implement Epetra_DistObject virtual methods + int CheckSizes(const Epetra_SrcDistObject& A); + + int CopyAndPermute(const Epetra_SrcDistObject & Source, + int NumSameIDs, + int NumPermuteIDs, + int * PermuteToLIDs, + int * PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + + int PackAndPrepare(const Epetra_SrcDistObject & Source, + int NumExportIDs, + int * ExportLIDs, + int & LenExports, + char * & Exports, + int & SizeOfPacket, + int * Sizes, + bool& VarSizes, + Epetra_Distributor & Distor); + + int UnpackAndCombine(const Epetra_SrcDistObject & Source, + int NumImportIDs, + int * ImportLIDs, + int LenImports, + char * Imports, + int & SizeOfPacket, + Epetra_Distributor & Distor, + Epetra_CombineMode CombineMode, + const Epetra_OffsetIndex * Indexor); + + int * Values_; + bool UserAllocated_; + bool Allocated_; +}; + +#endif /* EPETRA_INTVECTOR_H */ diff --git a/fastlib/trilinos/include/Epetra_InvOperator.h b/fastlib/trilinos/include/Epetra_InvOperator.h new file mode 100644 index 0000000000..cc65c54909 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_InvOperator.h @@ -0,0 +1,155 @@ + +/*@HEADER +// *********************************************************************** +// +// Epetra: Linear Algebra Services Package +// Copyright (2001) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +//@HEADER +*/ + +#ifndef EPETRA_INVOPERATOR_H +#define EPETRA_INVOPERATOR_H + +class Epetra_MultiVector; +class Epetra_BlockMap; +class Epetra_Comm; +#include +#include "Epetra_Operator.h" + +//! Epetra_InvOperator: An implementation of the Epetra_Operator class that reverses the role of Apply() and ApplyInverse() methods. +/*! The Epetra_InvOperator class implements Epetra_Operator using another pre-constructed Epetra_Operator object. + Once constructed, an Epetra_InvOperator can be used as the inverse of the input operator + object as long as the appropriate Apply and ApplyInverse methods are implemented in the original Epetra_Operator object. +*/ + +class Epetra_InvOperator: public virtual Epetra_Operator { + + public: + + //! @name Constructor + //@{ + //! Uses an Epetra_Operator instance to implement the Epetra_Operator interface. + /*! Facilitates the use of an Epetra_Operator instance as an inverse operator. + \param In - A fully-constructed Epetra_Operator object. + */ + Epetra_InvOperator(Epetra_Operator * operatorIn) { + operator_ = operatorIn; + Label_ = "Inverse of " + string(operatorIn->Label()); + return; + } + //! Destructor + virtual ~Epetra_InvOperator(){} + //@} + + //! @name Atribute set methods + //@{ + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param In + UseTranspose - If true, multiply by the transpose of operator, otherwise just use operator. + + \warning - This method has no effect and returns -1 as error code. + */ + int SetUseTranspose(bool UseTranspose){EPETRA_CHK_ERR(operator_->SetUseTranspose(UseTranspose)); return(0);} + //@} + + //! @name Mathematical functions + //@{ + + //! Returns the result of a Epetra_InvOperator applied to a Epetra_MultiVector X in Y. + /*! + \param In + X - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \warning - This method has no effect and returns -1 as error code. + */ + int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const {EPETRA_CHK_ERR(operator_->ApplyInverse(X,Y)); return(0);} + + //! Returns the result of a Epetra_InvOperator inverse applied to an Epetra_MultiVector X in Y. + /*! + \param In + X - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const{EPETRA_CHK_ERR(operator_->Apply(X,Y)); return(0);} + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f]. + + \warning This method must not be called unless HasNormInf() returns true. + */ + double NormInf() const {return(operator_->NormInf());} + + //! @name Atribute access functions + //@{ + + //! Returns a character string describing the operator + const char * Label() const {return(Label_.c_str());} + + //! Returns a pointer to the Epetra_Operator operator object that was used to create this Epetra_InvOperator object. + Epetra_Operator * Operator() const {return(operator_);} + + + //! Returns the current UseTranspose setting. + bool UseTranspose() const {return(operator_->UseTranspose());} + + //! Returns true if the \e this object can provide an approximate Inf-norm, false otherwise. + bool HasNormInf() const {return(operator_->HasNormInf());}; + + //! Returns a pointer to the Epetra_Comm communicator associated with this operator. + const Epetra_Comm & Comm() const {return(operator_->Comm());} + + //! Returns the Epetra_BlockMap object associated with the domain of this matrix operator. + const Epetra_Map & OperatorDomainMap() const + { + if (!UseTranspose()) return(operator_->OperatorRangeMap()); + else return(operator_->OperatorDomainMap()); + } + + //! Returns the Epetra_BlockMap object associated with the range of this matrix operator. + const Epetra_Map & OperatorRangeMap() const + { + if (!UseTranspose()) return(operator_->OperatorDomainMap()); + else return(operator_->OperatorRangeMap()); + } + //@} + + protected: + + Epetra_Operator * operator_; + string Label_; +}; + +#endif /* EPETRA_INVOPERATOR_H */ + diff --git a/fastlib/trilinos/include/Epetra_JadMatrix.h b/fastlib/trilinos/include/Epetra_JadMatrix.h new file mode 100644 index 0000000000..d1d6c3729c --- /dev/null +++ b/fastlib/trilinos/include/Epetra_JadMatrix.h @@ -0,0 +1,217 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_JADMATRIX_H +#define EPETRA_JADMATRIX_H + +#include "Epetra_BasicRowMatrix.h" +#include "Epetra_Map.h" +#include "Epetra_Comm.h" +#include "Epetra_SerialDenseVector.h" +#include "Epetra_IntSerialDenseVector.h" + + +class Epetra_Vector; +class Epetra_MultiVector; +class Epetra_Import; +class Epetra_Export; + +//! Epetra_JadMatrix: A class for constructing matrix objects optimized for common kernels. + +/*! The Epetra_JadMatrix class takes an existing Epetra_RowMatrix ojbect, analyzes it and + builds a jagged diagonal equivalent of it. Once constructed, it is also possible to + update the values of the matrix with values from another Epetra_RowMatrix that has + the identical structure. + +*/ + +class Epetra_JadMatrix: public Epetra_BasicRowMatrix { + + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_JadMatrix constuctor. + /* The constructor for this class requires a fully constructed instance of an Epetra_RowMatrix + object. + \param Matrix (In) An existing Epetra_RowMatrix. + \pre Matrix must have Matrix.Filled()==true. + */ + Epetra_JadMatrix(const Epetra_RowMatrix & Matrix); + + //! Epetra_JadMatrix Destructor + virtual ~Epetra_JadMatrix(); + //@} + + //! @name Post-construction modifications + //@{ + //! Update values using a matrix with identical structure. + /* Updates the values only using a matrix that has exactly the same structure as + the matrix used to construct this Epetra_JadMatrix object. Once the constructor + is called, the Matrix argument is no longer needed. + \param Matrix (In) An existing Epetra_RowMatrix with \e identical structure to + the matrix used to create this Epetra_JadMatrix. + \param CheckStructure (In) Optional argument, by default is false. If set to true, + the method will check to see if the structure of Matrix is compatible with + the structure of matrix used to create this Epetra_JadMatrix. Performing + this check has signficant overhead, so it should only be turned on for debugging. + \pre Matrix must have Matrix.Filled()==true. + */ + int UpdateValues(const Epetra_RowMatrix & Matrix, bool CheckStructure = false); + //@} + + //! @name Methods required for implementing Epetra_BasicRowMatrix + //@{ + + //! Returns a copy of the specified local row in user-provided arrays. + /*! + \param MyRow (In) - Local row to extract. + \param Length (In) - Length of Values and Indices. + \param NumEntries (Out) - Number of nonzero entries extracted. + \param Values (Out) - Extracted values for this row. + \param Indices (Out) - Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful, set to -1 if MyRow not valid, -2 if Length is too short (NumEntries will have required length). + */ + int ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, double *Values, int * Indices) const; + + //! Returns a reference to the ith entry in the matrix, along with its row and column index. + /*! + \param CurEntry (In) - Local entry to extract. + \param Value (Out) - Extracted reference to current values. + \param RowIndex (Out) - Row index for current entry. + \param ColIndex (Out) - Column index for current entry. + + \return Integer error code, set to 0 if successful, set to -1 if CurEntry not valid. + */ + int ExtractMyEntryView(int CurEntry, double * &Value, int & RowIndex, int & ColIndex) { + if (CurEntry>=NumMyNonzeros_) EPETRA_CHK_ERR(-1); + Value = &Values_[CurEntry]; + ColIndex = Indices_[CurEntry]; + for (int j=0; j=NumMyNonzeros_) EPETRA_CHK_ERR(-1); + Value = &Values_[CurEntry]; + ColIndex = Indices_[CurEntry]; + for (int j=0; j(A); Operator_ = A; } + + //! Set left-hand-side X of linear problem AX = B. + /*! Sets a pointer to a Epetra_MultiVector. No copy of the object is made. + */ + void SetLHS(Epetra_MultiVector * X) {X_ = X;} + + //! Set right-hand-side B of linear problem AX = B. + /*! Sets a pointer to a Epetra_MultiVector. No copy of the object is made. + */ + void SetRHS(Epetra_MultiVector * B) {B_ = B;} + //@} + + //! @name Computational methods + //@{ + //! Perform left scaling of a linear problem. + /*! Applies the scaling vector D to the left side of the matrix A() and + to the right hand side B(). Note that the operator must be an Epetra_RowMatrix, + not just an Epetra_Operator (the base class of Epetra_RowMatrix). + \param In + D - Vector containing scaling values. D[i] will be applied + to the ith row of A() and B(). + \return Integer error code, set to 0 if successful. Return -1 if operator is not a matrix. + */ + int LeftScale(const Epetra_Vector & D); + + //! Perform right scaling of a linear problem. + /*! Applies the scaling vector D to the right side of the matrix A(). + Apply the inverse of D to the initial guess. Note that the operator must be an Epetra_RowMatrix, + not just an Epetra_Operator (the base class of Epetra_RowMatrix). + \param In + D - Vector containing scaling values. D[i] will be applied + to the ith row of A(). 1/D[i] will be applied to the + ith row of B(). + \return Integer error code, set to 0 if successful. Return -1 if operator is not a matrix. + */ + int RightScale(const Epetra_Vector & D); + //@} + + //! @name Accessor methods + //@{ + //! Get a pointer to the operator A. + Epetra_Operator * GetOperator() const {return(Operator_);}; + //! Get a pointer to the matrix A. + Epetra_RowMatrix * GetMatrix() const {return(A_);}; + //! Get a pointer to the left-hand-side X. + Epetra_MultiVector * GetLHS() const {return(X_);}; + //! Get a pointer to the right-hand-side B. + Epetra_MultiVector * GetRHS() const {return(B_);}; + //! Get problem difficulty level. + ProblemDifficultyLevel GetPDL() const {return(PDL_);}; + //! Get operator symmetry bool. + bool IsOperatorSymmetric() const {return(OperatorSymmetric_);}; + //@} + + private: + + Epetra_Operator * Operator_; + Epetra_RowMatrix * A_; + Epetra_MultiVector * X_; + Epetra_MultiVector * B_; + + bool OperatorSymmetric_; + ProblemDifficultyLevel PDL_; + bool LeftScaled_; + bool RightScaled_; + Epetra_Vector * LeftScaleVector_; + Epetra_Vector * RightScaleVector_; + Epetra_LinearProblem & operator=(const Epetra_LinearProblem& Problem); +}; + +#endif /* EPETRA_LINEARPROBLEM_H */ diff --git a/fastlib/trilinos/include/Epetra_LocalMap.h b/fastlib/trilinos/include/Epetra_LocalMap.h new file mode 100644 index 0000000000..918a167460 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_LocalMap.h @@ -0,0 +1,115 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_LOCALMAP_H +#define EPETRA_LOCALMAP_H + +//! Epetra_LocalMap: A class for replicating vectors and matrices across multiple processors. + +/*! Small matrix and vector objects are often replicated on distributed memory + parallel machines. The Epetra_LocalMap class allows construction of these replicated + local objects and keeps information that describes + this distribution. + + Epetra_LocalMap allows the storage and retrieval of the following information. + Once a Epetra_Map is constructed any of the following attributes can + be obtained + by calling a query function that has the name as the attribute, e.g. to get the + value of NumGlobalPoints, you can call a function NumGlobalElements(). + For attributes that + are lists, the query functions return the list values in a user allocated array. + + +
      +
    • NumMyElements - The number of elements owned by the calling processor. +
    • IndexBase - The base integer value for indexed array references. Typically this is 0 + for C/C++ and 1 for Fortran, but it can be set to any integer value. +
    • Comm - The Epetra_Comm communicator. This communicator can in turn be queried for + processor rank and size information. +
    + + The Epetra_LocalMap class is actually a derived class of Epetra_Map. Epetra_Map is in turn derived + from Epetra_BlockMap. As such, Epetra_LocalMap has full access to all the functions in these other + map classes. + + In particular, the following function allows a boolean test: + +
      +
    • DistributedGlobal() - Returns false for a Epetra_LocalMap object. +
    + + \warning A Epetra_Comm object is required for all Epetra_LocalMap constructors. + + \internal In the current implementation, Epetra_Map is the base class for Epetra_LocalMap. + +*/ +#include "Epetra_Map.h" + +class Epetra_LocalMap : public Epetra_Map { + + public: + //! Epetra_LocalMap constructor for a user-defined replicate distribution of elements. + /*! Creates a map that puts NumMyElements on the calling processor. Each processor should + pass in the same value for NumMyElements. + + \param In + NumMyElements - Number of elements owned by the calling processor. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_Map object. + + */ + Epetra_LocalMap(int NumMyElements, int IndexBase, const Epetra_Comm& Comm); + + //! Epetra_LocalMap copy constructor. + + Epetra_LocalMap(const Epetra_LocalMap& map); + + //! Epetra_LocalMap destructor. + + virtual ~Epetra_LocalMap(); + + //! Assignment Operator + Epetra_LocalMap & operator=(const Epetra_LocalMap & map); + + private: + + int CheckInput(); + +}; +#endif /* EPETRA_LOCALMAP_H */ diff --git a/fastlib/trilinos/include/Epetra_Map.h b/fastlib/trilinos/include/Epetra_Map.h new file mode 100644 index 0000000000..14088fcb8b --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Map.h @@ -0,0 +1,214 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_MAP_H +#define EPETRA_MAP_H + +//! Epetra_Map: A class for partitioning vectors and matrices. + +/*! It is often the case that multiple matrix and vector objects have an identical distribution + of elements on a parallel machine. The Epetra_Map class keep information that describes + this distribution for matrices and vectors. + + Epetra_Map allows the storage and retrieval of the following information. Depending on the + constructor that is used, some of the information is defined by the user and some is + determined by the constructor. Once a Epetra_Map is constructed any of the following attributes can + be obtained + by calling a query function that has the name as the attribute, e.g. to get the + value of NumGlobalElements, you can call a function NumGlobalElements(). For attributes that + are lists, the query functions return the list values in a user allocated array. + +
      +
    • NumGlobalElements - The total number of elements across all processors. If this parameter and + NumMyElements are both passed into the constructor, one of the three cases will apply: +
        +
      1. If NumGlobalElements = NumMyElements (and not equal to zero) + the map is defined to be a local replicated + map. In this case, objects constructed using this map will be identically replicated across + all processors in the communicator. +
      2. If NumGlobalElements = -1 and NumMyElements is passed in then NumGlobalElements will + be computed as the sum of NumMyElements across all processors. +
      3. If neither of the above is true, NumGlobalElements will be checked against the sum of + NumMyElements across all processors. An error is issued if the comparison is not equal. +
      +
    • NumMyElements - The number of elements owned by the calling processor. +
    • MyGlobalElements - A list of length NumMyElements that contains the global element IDs + of the elements owned by the calling processor. +
    • IndexBase - The base integer value for indexed array references. Typically this is 0 + for C/C++ and 1 for Fortran, but it can be set to any integer value. +
    • Comm - The Epetra_Comm communicator. This communicator can in turn be queried for + processor rank and size information. +
    + + + In addition to the information above that is passed in to or created by the Epetra_Map constructor, + the following attributes are computed and available via query to the user using the same scheme + as above, e.g., use NumGlobalPoints() to get the value of NumGlobalPoints. + +
      +
    • NumGlobalPoints - The total number of points across all processors. +
    • NumMyPoints - The number of points on the calling processor. +
    • MinAllGID - The minimum global index value across all processors. +
    • MaxAllGID - The maximum global index value across all processors. +
    • MinMyGID - The minimum global index value on the calling processor. +
    • MaxMyGID - The maximum global index value on the calling processor. +
    • MinLID - The minimum local index value on the calling processor. +
    • MaxLID - The maximum local index value on the calling processor. +
    + + The following functions allow boolean tests for certain properties. + +
      +
    • LinearMap() - Returns true if the elements are distributed linear across processors, i.e., + processor 0 gets the first n/p elements, processor 1 gets the next n/p elements, etc. where + n is the number of elements and p is the number of processors. +
    • DistributedGlobal() - Returns true if the element space of the map spans more than one processor. + This will be true in most cases, but will be false in serial cases and for objects + that are created via the derived Epetra_LocalMap class. +
    + + \warning An Epetra_Comm object is required for all Epetra_Map constructors. + + \note In the current implementation, Epetra_BlockMap is the base class for Epetra_Map. + +*/ + +#include "Epetra_BlockMap.h" + +class Epetra_Map : public Epetra_BlockMap { + + public: + + //! Epetra_Map constructor for a Epetra-defined uniform linear distribution of elements. + /*! Creates a map that distributes NumGlobalElements elements evenly across all processors in the + Epetra_Comm communicator. If NumGlobalElements does not divide exactly into the number of processors, + the first processors in the communicator get one extra element until the remainder is gone. + + \param In + NumGlobalElements - Number of elements to distribute. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_Map object. + + */ + Epetra_Map(int NumGlobalElements, int IndexBase, const Epetra_Comm& Comm); + + + + + + //! Epetra_Map constructor for a user-defined linear distribution of elements. + /*! Creates a map that puts NumMyElements on the calling processor. If + NumGlobalElements=-1, the number of global elements will be + the computed sum of NumMyElements across all processors in the + Epetra_Comm communicator. + + \param In + NumGlobalElements - Number of elements to distribute. Must be + either -1 or equal to the computed sum of NumMyElements across all + processors in the Epetra_Comm communicator. + + \param In + NumMyElements - Number of elements owned by the calling processor. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_Map object. + + */ + Epetra_Map(int NumGlobalElements, int NumMyElements, int IndexBase, const Epetra_Comm& Comm); + + + + + + //! Epetra_Map constructor for a user-defined arbitrary distribution of elements. + /*! Creates a map that puts NumMyElements on the calling processor. The indices of the elements + are determined from the list MyGlobalElements. If + NumGlobalElements=-1, the number of global elements will be + the computed sum of NumMyElements across all processors in the + Epetra_Comm communicator. + + \param In + NumGlobalElements - Number of elements to distribute. Must be + either -1 or equal to the computed sum of NumMyElements across all + processors in the Epetra_Comm communicator. + + \param In + NumMyElements - Number of elements owned by the calling processor. + + \param In + MyGlobalElements - Integer array of length NumMyElements. The ith entry contains the + global index value of the ith element on this processor. Index values are not required to + be contiguous on a processor, or to be within the range of 0 to NumGlobalElements. As + long as the index values are consistently defined and used, any set of NumGlobalElements + distinct integer values is acceptable. + + \param In + IndexBase - Minimum index value used for arrays that use this map. Typically 0 for + C/C++ and 1 for Fortran. + + \param In + Comm - Epetra_Comm communicator containing information on the number of + processors. + + \return Pointer to a Epetra_Map object. + + */ + Epetra_Map(int NumGlobalElements, int NumMyElements, + const int *MyGlobalElements, + int IndexBase, const Epetra_Comm& Comm); + + //! Epetra_Map copy constructor. + Epetra_Map(const Epetra_Map& map); + + //! Epetra_Map destructor. + virtual ~Epetra_Map(void); + + //! Assignment Operator + Epetra_Map & operator=(const Epetra_Map & map); + +}; + +#endif /* EPETRA_MAP_H */ diff --git a/fastlib/trilinos/include/Epetra_MapColoring.h b/fastlib/trilinos/include/Epetra_MapColoring.h new file mode 100644 index 0000000000..c292b09f80 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_MapColoring.h @@ -0,0 +1,306 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_MAPCOLORING_H +#define EPETRA_MAPCOLORING_H +#include "Epetra_DistObject.h" +#include "Epetra_BlockMap.h" +#include "Epetra_Distributor.h" +class Epetra_HashTable; +class Epetra_Map; + +//! Epetra_MapColoring: A class for coloring Epetra_Map and Epetra_BlockMap objects. + +/*! This class allows the user to associate an integer value, i.e., a color, to each element of + an existing Epetra_Map or Epetra_BlockMap object. Colors may be assigned at construction, or + via set methods. Any elements that are not explicitly assigned a color are assigned the color + 0 (integer zero). + +This class has the following features: + +
      + +
    • A color (arbitrary integer label) can be associated locally with each element of a map. + Color assignment can be done +
        +
      1. all-at-once via the constructor, or +
      2. via operator[] (using LIDs) one-at-a-time +
      3. operator() (using GIDs) one-at-a-time +
      4. or some combination of the above. +
      + +Any element that is not explicitly colored takes on the default color. The default +color is implicitly zero, unless specified differently at the time of construction. + +
    • Color information may be accessed in the following ways: +
        +
      1. By local element ID (LID) - Returns the color of a specified LID, where the LID is associated + with the Epetra_Map or BlockMap that was passed in to the Epetra_MapColoring constructor. +
      2. By global element ID (GID) - Returns the color of the specified GID. There two methods + for accessing GIDs, one assumes the request is for GIDs owned by the calling processor, + the second allows arbitrary requested for GIDs, as long as the GID is defined on some processor + for the Epetra_Map or Epetra_BlockMap. +
      3. By color groups - Elements are grouped by color so that all elements of a given color can + be accessed. +
      4. Epetra_Map/Epetra_BlockMap pointers for a specified color - This facilitates + use of coloring with Epetra distributed objects that are distributed via the map + that was colored. For example, if users want to work with all rows of a matrix that have + a certain color, they can create a map for that color and use it to access only those rows. +
      + + +
    • The Epetra_MapColoring class implements the Epetra_DistObject interface. Therefore, a map coloring + can be computed for a map with a given distribution and then redistributed across the parallel machine. + For example, it would be possible to compute a map coloring on a single processor (perhaps because the + algorithm for computing the color assignment is too difficult to implement in parallel or because it + is cheap to run and not worth parallelizing), and then re-distribute the coloring using an Epetra_Export + or Epetra_Import object. +
    + +*/ + +class Epetra_MapColoring: public Epetra_DistObject { + + public: + + //! @name Constructors/destructors + //@{ + //! Epetra_MapColoring basic constructor. + /*! + \param In + Map - An Epetra_Map or Epetra_BlockMap (Note: Epetra_BlockMap is a base class of + Epetra_Map, so either can be passed in to this constructor. + \param In + DefaultColor - The integer value to use as the default color for this map. This constructor + will initially define the color of all map elements to the default color. + + \return Pointer to a Epetra_MapColoring object. + + */ + Epetra_MapColoring(const Epetra_BlockMap& Map, const int DefaultColor = 0); + + //! Epetra_MapColoring constructor. + /*! + \param In + Map - An Epetra_Map or Epetra_BlockMap (Note: Epetra_BlockMap is a base class of + Epetra_Map, so either can be passed in to this constructor. + + \param In + ElementColors - Array of dimension Map.NumMyElements() containing the list of colors + that should be assigned the map elements on this processor. If this argument is + set to 0 (zero), all elements will initially be assigned color 0 (zero). Element + colors can be modified by using methods described below. + \param In + DefaultColor - The color that will be assigned by default when no other value is specified. + This value has no meaning for this constructor, but is used by certain methods now and + in the future. + + \return Pointer to a Epetra_MapColoring object. + + */ + Epetra_MapColoring(const Epetra_BlockMap& Map, int * ElementColors, const int DefaultColor = 0); + + //! Epetra_MapColoring copy constructor. + + Epetra_MapColoring(const Epetra_MapColoring& Source); + + //! Epetra_MapColoring destructor. + + virtual ~Epetra_MapColoring(); + //@} + + //! @name Set Color methods + //@{ + + //! LID element color assignment method. + /*! Allows color assignment of ith LID: colormap[i] = color + \return MapColor(LID). + */ + int& operator [] (int LID) {ListsAreValid_ = false; return ElementColors_[LID];}; + + //! GID element color assignment method, Note: Valid only for GIDs owned by calling processor. + /*! Allows color assignment of specified GID \e only if the GID is owned by map on + the calling processor. If you are unsure about the ownership of a GID, check by using the MyGID() + method. MyGID(GID) returns true if the GID is owned by the calling processor. + \return MapColor(GID). + */ + int& operator () (int GID) {ListsAreValid_ = false; return ElementColors_[Map().LID(GID)];}; + //@} + + //! @name Local/Global color accessor methods + //@{ + //! LID element color access method. + /*! Returns color of ith LID: colormap[i] = color + \return MapColor[LID]. + */ + const int& operator [] (int LID) const { return ElementColors_[LID];}; + + //! GID element color assignment method, Note: Valid only for GIDs owned by calling processor. + /*! Allows color assignment of specified GID \e only if the GID is owned by map on + the calling processor. If you are unsure about the ownership, check by using the MyGID() + method on the map object. + \return MapColor(GID). + */ + const int& operator () (int GID) const {return ElementColors_[Map().LID(GID)];}; + //@} + + //! @name Color Information Access Methods + //@{ + //! Returns number of colors on the calling processor. + int NumColors() const {if (!ListsAreValid_) GenerateLists(); return(NumColors_);}; + + //! Returns maximum over all processors of the number of colors. + int MaxNumColors() const; + + //! Array of length NumColors() containing List of color values used in this coloring. + /*! Color values can be arbitrary integer values. As a result, a user of a previously + constructed MapColoring object may need to know exactly which color values are present. + This array contains that information as a sorted list of integer values. + */ + int * ListOfColors() const {if (!ListsAreValid_) GenerateLists(); return(ListOfColors_);}; + + //! Returns default color. + int DefaultColor() const {return(DefaultColor_);}; + + //! Returns number of map elements on calling processor having specified Color + int NumElementsWithColor(int Color) const; + + //! Returns pointer to array of Map LIDs associated with the specified color. + /*! Returns a pointer to a list of Map LIDs associated with the specified color. + This is a purely local list with no information about other processors. If there + are no LIDs associated with the specified color, the pointer is set to zero. + */ + int * ColorLIDList(int Color) const; + + //! Returns pointer to array of the colors associated with the LIDs on the calling processor. + /*! Returns a pointer to the list of colors associated with the elements on this processor + such that ElementColor[LID] is the color assigned to that LID. + */ + int * ElementColors() const{if (!ListsAreValid_) GenerateLists(); return(ElementColors_);}; + + //@} + //! @name Epetra_Map and Epetra_BlockMap generators + //@{ + //! Generates an Epetra_Map of the GIDs associated with the specified color. + /*! This method will create an Epetra_Map such that on each processor the GIDs associated with + the specified color will be part of the map on that processor. Note that this + method always generates an Epetra_Map, not an Epetra_BlockMap, even if the map associated + with this map coloring is a block map. Once the map is generated, the user is responsible for + deleting it. + */ + Epetra_Map * GenerateMap(int Color) const; + + //! Generates an Epetra_BlockMap of the GIDs associated with the specified color. + /*! This method will create an Epetra_BlockMap such that on each processor the GIDs associated with + the specified color will be part of the map on that processor. Note that this + method will generate an Epetra_BlockMap such that each element as the same element size as the + corresponding element of map associated with the map coloring. + Once the map is generated, the user is responsible for + deleting it. + */ + Epetra_BlockMap * GenerateBlockMap(int Color) const; + //@} + + //! @name I/O methods + //@{ + + //! Print method + virtual void Print(ostream & os) const; + //@} + + private: + int Allocate(int * ElementColors, int Increment); + int GenerateLists() const; + int DeleteLists() const; + bool InItemList(int ColorValue) const; + + // Routines to implement Epetra_DistObject virtual methods + + int CheckSizes(const Epetra_SrcDistObject& A); + int CopyAndPermute(const Epetra_SrcDistObject & Source, + int NumSameIDs, + int NumPermuteIDs, + int * PermuteToLIDs, + int * PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + + int PackAndPrepare(const Epetra_SrcDistObject & Source, + int NumExportIDs, + int * ExportLIDs, + int & LenExports, + char * & Exports, + int & SizeOfPacket, + int * Sizes, + bool & VarSizes, + Epetra_Distributor & Distor); + + int UnpackAndCombine(const Epetra_SrcDistObject & Source, + int NumImportIDs, + int * ImportLIDs, + int LenImports, + char * Imports, + int & SizeOfPacket, + Epetra_Distributor & Distor, + Epetra_CombineMode CombineMode, + const Epetra_OffsetIndex * Indexor ); + + + struct ListItem { + int ItemValue; + ListItem * NextItem; + + ListItem( const int itemValue = 0, ListItem * nextItem = 0) + : ItemValue(itemValue), NextItem(nextItem){} + + // Constructors commented out due to Intel v.7.1 compiler error (4/2005). + //ListItem(const Epetra_MapColoring::ListItem & Item); // Make these inaccessible + //ListItem & operator=(const Epetra_MapColoring::ListItem & Item); + }; + + int DefaultColor_; + mutable Epetra_HashTable * ColorIDs_; + mutable ListItem * FirstColor_; + mutable int NumColors_; + mutable int * ListOfColors_; + mutable int * ColorCount_; + mutable int * ElementColors_; + mutable int ** ColorLists_; + bool Allocated_; + mutable bool ListsAreGenerated_; + mutable bool ListsAreValid_; + + Epetra_MapColoring & operator=(const Epetra_MapColoring & Coloring); // Make these inaccessible + + + +}; + +#endif /* EPETRA_MAPCOLORING_H */ diff --git a/fastlib/trilinos/include/Epetra_MultiVector.h b/fastlib/trilinos/include/Epetra_MultiVector.h new file mode 100644 index 0000000000..d279e7671e --- /dev/null +++ b/fastlib/trilinos/include/Epetra_MultiVector.h @@ -0,0 +1,1031 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_MULTIVECTOR_H +#define EPETRA_MULTIVECTOR_H + +class Epetra_Comm; +class Epetra_BlockMap; +class Epetra_Map; +class Epetra_Import; +class Epetra_Export; +class Epetra_Distributor; +class Epetra_Vector; + +#include "Epetra_DistObject.h" +#include "Epetra_CompObject.h" +#include "Epetra_BLAS.h" +#include "Epetra_Util.h" + +//! Epetra_MultiVector: A class for constructing and using dense multi-vectors, vectors and matrices in parallel. + +/*! The Epetra_MultiVector class enables the construction and use of real-valued, + double-precision dense vectors, multi-vectors, + and matrices in a distributed memory environment. The dimensions and distribution of the dense + multi-vectors is determined in part by a Epetra_Comm object, a Epetra_Map (or Epetra_LocalMap + or Epetra_BlockMap) and the number of vectors passed to the constructors described below. + + There are several concepts that important for understanding the Epetra_MultiVector class: + +
      +
    • Multi-vectors, Vectors and Matrices. +
        +
      • Vector - A list of real-valued, double-precision numbers. Also a multi-vector with one vector. +
      • Multi-Vector - A collection of one or more vectors, all having the same length and distribution. +
      • (Dense) Matrix - A special form of multi-vector such that stride in memory between any + two consecutive vectors in the multi-vector is the same for all vectors. This is identical + to a two-dimensional array in Fortran and plays an important part in high performance + computations. +
      +
    • Distributed Global vs. Replicated Local. +
        +
      • Distributed Global Multi-vectors - In most instances, a multi-vector will be partitioned + across multiple memory images associated with multiple processors. In this case, there is + a unique copy of each element and elements are spread across all processors specified by + the Epetra_Comm communicator. +
      • Replicated Local Multi-vectors - Some algorithms use multi-vectors that are too small to + be distributed across all processors, the Hessenberg matrix in a GMRES + computation. In other cases, such as with block iterative methods, block dot product + functions produce small + dense matrices that are required by all processors. Replicated local multi-vectors handle + these types of situation. +
      +
    • Multi-vector Functions vs. Dense Matrix Functions. +
        +
      • Multi-vector functions - These functions operate simultaneously but independently + on each vector in the multi-vector and produce individual results for each vector. +
      • Dense matrix functions - These functions operate on the multi-vector as a matrix, + providing access to selected dense BLAS and LAPACK operations. +
      +
    + + Constructing Epetra_MultiVectors + + Except for the basic constructor and copy constructor, Epetra_MultiVector constructors + have two data access modes: +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the multi-vector. +
    + + \warning View mode is \e extremely dangerous from a data hiding perspective. + Therefore, we strongly encourage users to develop code using Copy mode first and + only use the View mode in a secondary optimization phase. + + All Epetra_MultiVector constructors require a map argument that describes the layout of elements + on the parallel machine. Specifically, + \c map is a Epetra_Map, Epetra_LocalMap or Epetra_BlockMap object describing the desired + memory layout for the multi-vector. + + There are six different Epetra_MultiVector constructors: +
      +
    • Basic - All values are zero. +
    • Copy - Copy an existing multi-vector. +
    • Copy from or make view of two-dimensional Fortran style array. +
    • Copy from or make view of an array of pointers. +
    • Copy or make view of a list of vectors from another Epetra_MultiVector object. +
    • Copy or make view of a range of vectors from another Epetra_MultiVector object. +
    + + Extracting Data from Epetra_MultiVectors + + Once a Epetra_MultiVector is constructed, it is possible to extract a copy of the values or create + a view of them. + + \warning ExtractView functions are \e extremely dangerous from a data hiding perspective. + For both ExtractView fuctions, there is a corresponding ExtractCopy function. We + strongly encourage users to develop code using ExtractCopy functions first and + only use the ExtractView functions in a secondary optimization phase. + + There are four Extract functions: +
      +
    • ExtractCopy - Copy values into a user-provided two-dimensional array. +
    • ExtractCopy - Copy values into a user-provided array of pointers. +
    • ExtractView - Set user-provided two-dimensional array parameters + to point to Epetra_MultiVector data. +
    • ExtractView - Set user-provided array of pointer parameters + to point to Epetra_MultiVector data. +
    + + Vector, Matrix and Utility Functions + + Once a Epetra_MultiVector is constructed, a variety of mathematical functions can be applied to + the individual vectors. Specifically: +
      +
    • Dot Products. +
    • Vector Updates. +
    • \e p Norms. +
    • Weighted Norms. +
    • Minimum, Maximum and Average Values. +
    + + In addition, a matrix-matrix multiply function supports a variety of operations on any viable + combination of global distributed and local replicated multi-vectors using calls to DGEMM, a + high performance kernel for matrix operations. In the near future we will add support for calls + to other selected BLAS and LAPACK functions. + + Counting Floating Point Operations + + Each Epetra_MultiVector object keep track of the number + of \e serial floating point operations performed using the specified object as the \e this argument + to the function. The Flops() function returns this number as a double precision number. Using this + information, in conjunction with the Epetra_Time class, one can get accurate parallel performance + numbers. The ResetFlops() function resets the floating point counter. + + \warning A Epetra_Map, Epetra_LocalMap or Epetra_BlockMap object is required for all + Epetra_MultiVector constructors. + +*/ + +//========================================================================== +class Epetra_MultiVector: public Epetra_DistObject, public Epetra_CompObject, public Epetra_BLAS { + + public: + + //! @name Constructors/destructors + //@{ + //! Basic Epetra_MultiVector constuctor. + /*! Creates a Epetra_MultiVector object and, by default, fills with zero values. + + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + + \warning Note that, because Epetra_LocalMap + derives from Epetra_Map and Epetra_Map derives from Epetra_BlockMap, this constructor works + for all three types of Epetra map classes. + \param In + NumVectors - Number of vectors in multi-vector. + \param In + zeroOut - If true then the allocated memory will be zeroed + out initialy. If false then this memory will not + be touched which can be significantly faster. + \return Pointer to a Epetra_MultiVector. + + */ + Epetra_MultiVector(const Epetra_BlockMap& Map, int NumVectors, bool zeroOut = true); + + //! Epetra_MultiVector copy constructor. + + Epetra_MultiVector(const Epetra_MultiVector& Source); + + //! Set multi-vector values from two-dimensional array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + \param In + A - Pointer to an array of double precision numbers. The first vector starts at A. + The second vector starts at A+MyLDA, the third at A+2*MyLDA, and so on. + \param In + MyLDA - The "Leading Dimension", or stride between vectors in memory. + \warning This value refers to the stride on the calling processor. Thus it is a + local quantity, not a global quantity. + \param In + NumVectors - Number of vectors in multi-vector. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_MultiVector(Epetra_DataAccess CV, const Epetra_BlockMap& Map, + double *A, int MyLDA, int NumVectors); + + //! Set multi-vector values from array of pointers. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + \param In + ArrayOfPointers - An array of pointers such that ArrayOfPointers[i] points to the memory + location containing ith vector to be copied. + \param In + NumVectors - Number of vectors in multi-vector. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_MultiVector(Epetra_DataAccess CV, const Epetra_BlockMap& Map, + double **ArrayOfPointers, int NumVectors); + + //! Set multi-vector values from list of vectors in an existing Epetra_MultiVector. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Source - An existing fully constructed Epetra_MultiVector. + \param In + Indices - Integer list of the vectors to copy. + \param In + NumVectors - Number of vectors in multi-vector. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_MultiVector(Epetra_DataAccess CV, + const Epetra_MultiVector& Source, int *Indices, int NumVectors); + + //! Set multi-vector values from range of vectors in an existing Epetra_MultiVector. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Source - An existing fully constructed Epetra_MultiVector. + \param In + StartIndex - First of the vectors to copy. + \param In + NumVectors - Number of vectors in multi-vector. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_MultiVector(Epetra_DataAccess CV, + const Epetra_MultiVector& Source, int StartIndex, + int NumVectors); + + //! Epetra_MultiVector destructor. + virtual ~Epetra_MultiVector(); + //@} + + //! @name Post-construction modification routines + //@{ + + //! Replace current value at the specified (GlobalRow, VectorIndex) location with ScalarValue. + /*! + Replaces the existing value for a single entry in the multivector. The + specified global row must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + If the map associated with this multivector is an Epetra_BlockMap, only the first point entry associated + with the global row will be modified. To modify a different point entry, use the other version of + this method + + \param In + GlobalRow - Row of Multivector to modify in global index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if GlobalRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(). + */ + int ReplaceGlobalValue(int GlobalRow, int VectorIndex, double ScalarValue); + + + //! Replace current value at the specified (GlobalBlockRow, BlockRowOffset, VectorIndex) location with ScalarValue. + /*! + Replaces the existing value for a single entry in the multivector. The + specified global block row and block row offset + must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + \param In + GlobalBlockRow - BlockRow of Multivector to modify in global index space. + \param In + BlockRowOffset - Offset into BlockRow of Multivector to modify in global index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if GlobalRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(), set to -2 if BlockRowOffset is out-of-range. + */ + int ReplaceGlobalValue(int GlobalBlockRow, int BlockRowOffset, int VectorIndex, double ScalarValue); + + + //! Adds ScalarValue to existing value at the specified (GlobalRow, VectorIndex) location. + /*! + Sums the given value into the existing value for a single entry in the multivector. The + specified global row must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + If the map associated with this multivector is an Epetra_BlockMap, only the first point entry associated + with the global row will be modified. To modify a different point entry, use the other version of + this method + + \param In + GlobalRow - Row of Multivector to modify in global index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if GlobalRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(). + */ + int SumIntoGlobalValue(int GlobalRow, int VectorIndex, double ScalarValue); + + + //! Adds ScalarValue to existing value at the specified (GlobalBlockRow, BlockRowOffset, VectorIndex) location. + /*! + Sums the given value into the existing value for a single entry in the multivector. The + specified global block row and block row offset + must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + \param In + GlobalBlockRow - BlockRow of Multivector to modify in global index space. + \param In + BlockRowOffset - Offset into BlockRow of Multivector to modify in global index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if GlobalRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(), set to -2 if BlockRowOffset is out-of-range. + */ + int SumIntoGlobalValue(int GlobalBlockRow, int BlockRowOffset, int VectorIndex, double ScalarValue); + + //! Replace current value at the specified (MyRow, VectorIndex) location with ScalarValue. + /*! + Replaces the existing value for a single entry in the multivector. The + specified local row must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + This method is intended for use with vectors based on an Epetra_Map. If used + on a vector based on a non-trivial Epetra_BlockMap, this will update only block + row 0, i.e. + + Epetra_MultiVector::ReplaceMyValue ( MyRow, VectorIndex, ScalarValue ) is + equivalent to: + Epetra_MultiVector::ReplaceMyValue ( 0, MyRow, VectorIndex, ScalarValue ) + + + \param In + MyRow - Row of Multivector to modify in local index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if MyRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(). + */ + int ReplaceMyValue(int MyRow, int VectorIndex, double ScalarValue); + + + //! Replace current value at the specified (MyBlockRow, BlockRowOffset, VectorIndex) location with ScalarValue. + /*! + Replaces the existing value for a single entry in the multivector. The + specified local block row and block row offset + must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + \param In + MyBlockRow - BlockRow of Multivector to modify in local index space. + \param In + BlockRowOffset - Offset into BlockRow of Multivector to modify in local index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if MyRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(), set to -2 if BlockRowOffset is out-of-range. + */ + int ReplaceMyValue(int MyBlockRow, int BlockRowOffset, int VectorIndex, double ScalarValue); + + + //! Adds ScalarValue to existing value at the specified (MyRow, VectorIndex) location. + /*! + Sums the given value into the existing value for a single entry in the multivector. The + specified local row must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + If the map associated with this multivector is an Epetra_BlockMap, only the first point entry associated + with the local row will be modified. To modify a different point entry, use the other version of + this method + + \param In + MyRow - Row of Multivector to modify in local index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if MyRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(). + */ + int SumIntoMyValue(int MyRow, int VectorIndex, double ScalarValue); + + + //! Adds ScalarValue to existing value at the specified (MyBlockRow, BlockRowOffset, VectorIndex) location. + /*! + Sums the given value into the existing value for a single entry in the multivector. The + specified local block row and block row offset + must correspond to a GID owned by the map of the multivector on the + calling processor. In other words, this method does not perform cross-processor communication. + + \param In + MyBlockRow - BlockRow of Multivector to modify in local index space. + \param In + BlockRowOffset - Offset into BlockRow of Multivector to modify in local index space. + \param In + VectorIndex - Vector within MultiVector that should to modify. + \param In + ScalarValue - Value to add to existing value. + + \return Integer error code, set to 0 if successful, set to 1 if MyRow not associated with calling processor + set to -1 if VectorIndex >= NumVectors(), set to -2 if BlockRowOffset is out-of-range. + */ + int SumIntoMyValue(int MyBlockRow, int BlockRowOffset, int VectorIndex, double ScalarValue); + + //! Initialize all values in a multi-vector with constant value. + /*! + \param In + ScalarConstant - Value to use. + + \return Integer error code, set to 0 if successful. + */ + int PutScalar (double ScalarConstant); + + //! Set multi-vector values to random numbers. + /*! MultiVector uses the random number generator provided by Epetra_Util. + The multi-vector values will be set to random values on the interval (-1.0, 1.0). + + \return Integer error code, set to 0 if successful. + + */ + int Random(); + + //@} + + //! @name Extraction methods + //@{ + + //! Put multi-vector values into user-provided two-dimensional array. + /*! + \param Out + A - Pointer to memory space that will contain the multi-vector values. + The first vector will be copied to the memory pointed to by A. + The second vector starts at A+MyLDA, the third at A+2*MyLDA, and so on. + \param In + MyLDA - The "Leading Dimension", or stride between vectors in memory. + \warning This value refers to the stride on the calling processor. Thus it is a + local quantity, not a global quantity. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + int ExtractCopy(double *A, int MyLDA) const; + + //! Put multi-vector values into user-provided array of pointers. + /*! + \param Out + ArrayOfPointers - An array of pointers to memory space that will contain the + multi-vector values, such that ArrayOfPointers[i] points to the memory + location where the ith vector to be copied. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + int ExtractCopy(double **ArrayOfPointers) const; + + // ExtractView functions + + + //! Set user-provided addresses of A and MyLDA. + /*! + \param + A (Out) - Address of a pointer to that will be set to point to the values of the multi-vector. + The first vector will be at the memory pointed to by A. + The second vector starts at A+MyLDA, the third at A+2*MyLDA, and so on. + \param + MyLDA (Out) - Address of the "Leading Dimension", or stride between vectors in memory. + \warning This value refers to the stride on the calling processor. Thus it is a + local quantity, not a global quantity. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + int ExtractView(double **A, int *MyLDA) const; + + //! Set user-provided addresses of ArrayOfPointers. + /*! + \param + ArrayOfPointers (Out) - Address of array of pointers to memory space that will set to the + multi-vector array of pointers, such that ArrayOfPointers[i] points to the memory + location where the ith vector is located. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + int ExtractView(double ***ArrayOfPointers) const; + + //@} + + //! @name Mathematical methods + //@{ + + //! Computes dot product of each corresponding pair of vectors. + /*! + \param In + A - Multi-vector to be used with the "\e this" multivector. + \param Out + Result - Result[i] will contain the ith dot product result. + + \return Integer error code, set to 0 if successful. + */ + int Dot(const Epetra_MultiVector& A, double *Result) const; + + //! Puts element-wise absolute values of input Multi-vector in target. + /*! + \param In + A - Input Multi-vector. + \param Out + \e this will contain the absolute values of the entries of A. + + \return Integer error code, set to 0 if successful. + + Note: It is possible to use the same argument for A and \e this. + */ + int Abs(const Epetra_MultiVector& A); + + //! Puts element-wise reciprocal values of input Multi-vector in target. + /*! + \param In + A - Input Multi-vector. + \param Out + \e this will contain the element-wise reciprocal values of the entries of A. + + \return Integer error code, set to 0 if successful. Returns 2 if some entry + is too small, but not zero. Returns 1 if some entry is zero. + + Note: It is possible to use the same argument for A and \e this. Also, + if a given value of A is smaller than Epetra_DoubleMin (defined in Epetra_Epetra.h), + but nonzero, then the return code is 2. If an entry is zero, the return code + is 1. However, in all cases the reciprocal value is still used, even + if a NaN is the result. + */ + int Reciprocal(const Epetra_MultiVector& A); + + //! Scale the current values of a multi-vector, \e this = ScalarValue*\e this. + /*! + \param In + ScalarValue - Scale value. + \param Out + \e This - Multi-vector with scaled values. + + \return Integer error code, set to 0 if successful. + */ + int Scale(double ScalarValue); + + //! Replace multi-vector values with scaled values of A, \e this = ScalarA*A. + /*! + \param In + ScalarA - Scale value. + \param In + A - Multi-vector to copy. + \param Out + \e This - Multi-vector with values overwritten by scaled values of A. + + \return Integer error code, set to 0 if successful. + */ + int Scale(double ScalarA, const Epetra_MultiVector& A); + + //! Update multi-vector values with scaled values of A, \e this = ScalarThis*\e this + ScalarA*A. + /*! + \param In + ScalarA - Scale value for A. + \param In + A - Multi-vector to add. + \param In + ScalarThis - Scale value for \e this. + \param Out + \e This - Multi-vector with updatede values. + + \return Integer error code, set to 0 if successful. + */ + int Update(double ScalarA, const Epetra_MultiVector& A, double ScalarThis); + + //! Update multi-vector with scaled values of A and B, \e this = ScalarThis*\e this + ScalarA*A + ScalarB*B. + /*! + \param In + ScalarA - Scale value for A. + \param In + A - Multi-vector to add. + \param In + ScalarB - Scale value for B. + \param In + B - Multi-vector to add. + \param In + ScalarThis - Scale value for \e this. + \param Out + \e This - Multi-vector with updatede values. + + \return Integer error code, set to 0 if successful. + */ + int Update(double ScalarA, const Epetra_MultiVector& A, + double ScalarB, const Epetra_MultiVector& B, double ScalarThis); + + //! Compute 1-norm of each vector in multi-vector. + /*! + \param Out + Result - Result[i] contains 1-norm of ith vector. + + \return Integer error code, set to 0 if successful. + */ + int Norm1 (double * Result) const; + + //! Compute 2-norm of each vector in multi-vector. + /*! + \param Out + Result - Result[i] contains 2-norm of ith vector. + + \return Integer error code, set to 0 if successful. + */ + int Norm2 (double * Result) const; + + //! Compute Inf-norm of each vector in multi-vector. + /*! + \param Out + Result - Result[i] contains Inf-norm of ith vector. + + \return Integer error code, set to 0 if successful. + */ + int NormInf (double * Result) const; + + //! Compute Weighted 2-norm (RMS Norm) of each vector in multi-vector. + /*! + \param In + Weights - Multi-vector of weights. If Weights contains a single vector, + that vector will be used as the weights for all vectors of \e this. Otherwise, + Weights should have the same number of vectors as \e this. + \param Out + Result - Result[i] contains the weighted 2-norm of ith vector. Specifically + if we denote the ith vector in the multivector by \f$x\f$, and the ith weight + vector by \f$w\f$ and let j represent the jth entry of each vector, on return + Result[i] will contain the following result: + \f[\sqrt{(1/n)\sum_{j=1}^n(x_j/w_j)^2}\f], + where \f$n\f$ is the global length of the vectors. + + \return Integer error code, set to 0 if successful. + */ + int NormWeighted (const Epetra_MultiVector& Weights, double * Result) const; + + //! Compute minimum value of each vector in multi-vector. + /*! Note that the vector contents must be already initialized for this + function to compute a well-defined result. The length of the + vector need not be greater than zero on all processors. If length is + greater than zero on any processor then a valid result will be computed. + \param Out + Result - Result[i] contains minimum value of ith vector. + + \return Integer error code, set to 0 if successful. + */ + int MinValue (double * Result) const; + + //! Compute maximum value of each vector in multi-vector. + /*! Note that the vector contents must be already initialized for this + function to compute a well-defined result. The length of the + vector need not be greater than zero on all processors. If length is + greater than zero on any processor then a valid result will be computed. + \param Out + Result - Result[i] contains maximum value of ith vector. + + \return Integer error code, set to 0 if successful. + */ + int MaxValue (double * Result) const; + + //! Compute mean (average) value of each vector in multi-vector. + /*! + \param Out + Result - Result[i] contains mean value of ith vector. + + \return Integer error code, set to 0 if successful. + */ + int MeanValue (double * Result) const; + + + //! Matrix-Matrix multiplication, \e this = ScalarThis*\e this + ScalarAB*A*B. + /*! This function performs a variety of matrix-matrix multiply operations, interpreting + the Epetra_MultiVectors (\e this-aka C , A and B) as 2D matrices. Variations are due to + the fact that A, B and C can be local replicated or global distributed + Epetra_MultiVectors and that we may or may not operate with the transpose of + A and B. Possible cases are: + \verbatim + + Total of 32 case (2^5). + Num + OPERATIONS case Notes + 1) C(local) = A^X(local) * B^X(local) 4 (X=Transpose or Not, No comm needed) + 2) C(local) = A^T(distr) * B (distr) 1 (2D dot product, replicate C) + 3) C(distr) = A (distr) * B^X(local) 2 (2D vector update, no comm needed) + + Note that the following operations are not meaningful for + 1D distributions: + + 1) C(local) = A^T(distr) * B^T(distr) 1 + 2) C(local) = A (distr) * B^X(distr) 2 + 3) C(distr) = A^X(local) * B^X(local) 4 + 4) C(distr) = A^X(local) * B^X(distr) 4 + 5) C(distr) = A^T(distr) * B^X(local) 2 + 6) C(local) = A^X(distr) * B^X(local) 4 + 7) C(distr) = A^X(distr) * B^X(local) 4 + 8) C(local) = A^X(local) * B^X(distr) 4 + + \endverbatim + + \param In + TransA - Operate with the transpose of A if = 'T', else no transpose if = 'N'. + \param In + TransB - Operate with the transpose of B if = 'T', else no transpose if = 'N'. + + \param In + ScalarAB - Scalar to multiply with A*B. + \param In + A - Multi-vector. + \param In + B - Multi-vector. + \param In + ScalarThis - Scalar to multiply with \e this. + + \return Integer error code, set to 0 if successful. + + \warning {Each multi-vector A, B and \e this is checked if it has constant stride using the + ConstantStride() query function. If it does not have constant stride, a temporary + copy is made and used for the computation. This activity is transparent to the user, + except that there is memory and computation overhead. All temporary space is deleted + prior to exit.} + + */ + int Multiply(char TransA, char TransB, double ScalarAB, + const Epetra_MultiVector& A, const Epetra_MultiVector& B, + double ScalarThis ); + + + + //! Multiply a Epetra_MultiVector with another, element-by-element. + /*! This function supports diagonal matrix multiply. A is usually a single vector + while B and \e this may have one or more columns. Note that B and \e this must + have the same shape. A can be one vector or have the same shape as B. The actual + computation is \e this = ScalarThis * \e this + ScalarAB * B @ A where @ denotes element-wise + multiplication. + */ + int Multiply(double ScalarAB, const Epetra_MultiVector& A, const Epetra_MultiVector& B, + double ScalarThis ); + + + //! Multiply a Epetra_MultiVector by the reciprocal of another, element-by-element. + /*! This function supports diagonal matrix scaling. A is usually a single vector + while B and \e this may have one or more columns. Note that B and \e this must + have the same shape. A can be one vector or have the same shape as B. The actual + computation is \e this = ScalarThis * \e this + ScalarAB * B @ A where @ denotes element-wise + division. + */ + int ReciprocalMultiply(double ScalarAB, const Epetra_MultiVector& A, const Epetra_MultiVector& B, + double ScalarThis ); + + //@} + + //! @name Random number utilities + //@{ + + + //! Set seed for Random function. + /*! + \param In + Seed - Should be an integer on the interval (0, 2^31-1). + + \return Integer error code, set to 0 if successful. + */ + int SetSeed(unsigned int Seed){return(Util_.SetSeed(Seed));}; + + //! Get seed from Random function. + /*! + \return Current random number seed. + */ + unsigned int Seed(){return(Util_.Seed());}; + + //@} + + //! @name Overloaded operators + //@{ + + //! = Operator. + /*! + \param In + A - Epetra_MultiVector to copy. + + \return Epetra_MultiVector. + */ + Epetra_MultiVector& operator = (const Epetra_MultiVector& Source); + + // Local element access functions + + // + + //! Vector access function. + /*! + \return Pointer to the array of doubles containing the local values of the ith vector in the multi-vector. + */ + double*& operator [] (int i) { return Pointers_[i]; } + //! Vector access function. + /*! + \return Pointer to the array of doubles containing the local values of the ith vector in the multi-vector. + */ + // const double*& operator [] (int i) const; + double * const & operator [] (int i) const { return Pointers_[i]; } + + //! Vector access function. + /*! + \return An Epetra_Vector pointer to the ith vector in the multi-vector. + */ + Epetra_Vector * & operator () (int i); + //! Vector access function. + /*! + \return An Epetra_Vector pointer to the ith vector in the multi-vector. + */ + const Epetra_Vector * & operator () (int i) const; + + //@} + + //! @name Attribute access functions + //@{ + + //! Returns the number of vectors in the multi-vector. + int NumVectors() const {return(NumVectors_);}; + + //! Returns the local vector length on the calling processor of vectors in the multi-vector. + int MyLength() const {return(MyLength_);}; + + //! Returns the global vector length of vectors in the multi-vector. + int GlobalLength() const {return(GlobalLength_);}; + + //! Returns the stride between vectors in the multi-vector (only meaningful if ConstantStride() is true). + int Stride() const {return(Stride_);}; + + //! Returns true if this multi-vector has constant stride between vectors. + bool ConstantStride() const {return(ConstantStride_);}; + //@} + + /** Replace map, only if new map has same point-structure as current map. + return 0 if map is replaced, -1 if not. + */ + int ReplaceMap(const Epetra_BlockMap& map); + + //! @name I/O methods + //@{ + + //! Print method + virtual void Print(ostream & os) const; + //@} + + //! @name Expert-only unsupported methods + //@{ + + //! Reset the view of an existing multivector to point to new user data. + /*! Allows the (very) light-weight replacement of multivector values for an + existing multivector that was constructed using an Epetra_DataAccess mode of View. + No checking is performed to see if the array of values passed in contains valid + data. It is assumed that the user has verified the integrity of data before calling + this method. This method is useful for situations where a multivector is needed + for use with an Epetra operator or matrix and the user is not passing in a multivector, + or the multivector is being passed in with another map that is not exactly compatible + with the operator, but has the correct number of entries. + + This method is used by AztecOO and Ifpack in the matvec, and solve methods to improve + performance and reduce repeated calls to constructors and destructors. + + @param ArrayOfPointers Contains the array of pointers containing the multivector data. + + \return Integer error code, set to 0 if successful, -1 if the multivector was not created as a View. + + \warning This method is extremely dangerous and should only be used by experts. + */ + + int ResetView(double ** ArrayOfPointers); + + //! Get pointer to MultiVector values + double* Values() const {return Values_;}; + + //! Get pointer to individual vector pointers + double** Pointers() const {return Pointers_;}; + //@} + + // Expert-only function + int Reduce(); + + protected: + + // Internal utilities + void Assign(const Epetra_MultiVector& rhs); + int CheckInput(); + + double *Values_; // local MultiVector coefficients + + private: + + + // Internal utilities + + int AllocateForCopy(void); + int DoCopy(void); + + inline void UpdateDoubleTemp() const + {if (DoubleTemp_==0) DoubleTemp_=new double[NumVectors_+1]; return;} + + inline void UpdateVectors() const {if (Vectors_==0) { Vectors_ = new Epetra_Vector *[NumVectors_]; + for (int i=0; i= 2 - All values (except zero) reported. + + Default is set to 1. + */ + static void SetTracebackMode(int TracebackModeValue); + + //! Get the value of the Epetra_Object error report mode. + static int GetTracebackMode(); + + //! Get the output stream for error reporting + static std::ostream& GetTracebackStream(); + + //@} + + //! @name Miscellaneous + //@{ + + //! Print object to an output stream + //! Print method + virtual void Print(ostream & os) const; + + //! Error reporting method + virtual int ReportError(const string Message, int ErrorCode) const; + //@} + + +// TracebackMode controls how much traceback information is printed when run time +// integer errors are detected: +// = 0 - No information report +// = 1 - Fatal (negative) values are reported +// = 2 - All values (except zero) reported. + +// Default is set to 1. Can be set to different value using SetTracebackMode() method in +// Epetra_Object class + static int TracebackMode; + + + protected: + string toString(const int& x) const { + char s[100]; + sprintf(s, "%d", x); + return string(s); +} + + string toString(const double& x) const { + char s[100]; + sprintf(s, "%g", x); + return string(s); +} + + + private: + Epetra_Object& operator=(const Epetra_Object& src) { + SetLabel(src.Label()); + return *this; + } + + char * Label_; + +}; + +inline ostream& operator<<(ostream& os, const Epetra_Object& obj) +{ + if (Epetra_FormatStdout) { +/* const Epetra_fmtflags olda = os.setf(ios::right,ios::adjustfield); + const Epetra_fmtflags oldf = os.setf(ios::scientific,ios::floatfield); + const int oldp = os.precision(12); */ + + os << obj.Label() << endl; + obj.Print(os); + +/* os.setf(olda,ios::adjustfield); + os.setf(oldf,ios::floatfield); + os.precision(oldp); */ + } + else { + + os << obj.Label(); + obj.Print(os); + } + + return os; +} + +/** \brief Macro for testing for and throwing and int exception for objects + * derived from Epetra_Object. + * + * This macro adds the file name and line number to teh + */ +#define EPETRA_TEST_FOR_EXCEPTION(throw_exception_test,errCode,msg) \ +{ \ + const bool throw_exception = (throw_exception_test); \ + if(throw_exception) { \ + std::ostringstream omsg; \ + omsg \ + << __FILE__ << ":" << __LINE__ << ":" \ + << " Throw test that evaluated to true: "#throw_exception_test << ":" \ + << "Error message : " << msg; \ + throw ReportError(omsg.str(),errCode); \ + } \ +} + +#endif /* EPETRA_OBJECT_H */ diff --git a/fastlib/trilinos/include/Epetra_OffsetIndex.h b/fastlib/trilinos/include/Epetra_OffsetIndex.h new file mode 100644 index 0000000000..10bef946d1 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_OffsetIndex.h @@ -0,0 +1,108 @@ +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_OFFSETINDEX_H +#define EPETRA_OFFSETINDEX_H + +#include "Epetra_Object.h" + +class Epetra_Import; +class Epetra_Export; +class Epetra_CrsGraph; +class Epetra_Distributor; + +//! Epetra_OffsetIndex: This class builds index for efficient mapping of data from one Epetra_CrsGraph based object to another. + +/*! Epetra_OffsetIndex generates and index of offsets allowing direct access to data + for Import/Export operations on Epetra_CrsGraph based objects such as Epetra_CrsMatrix. +*/ + +class Epetra_OffsetIndex: public Epetra_Object { + + public: + + //! Constructs a Epetra_OffsetIndex object from the graphs and an importer. + Epetra_OffsetIndex( const Epetra_CrsGraph & SourceGraph, + const Epetra_CrsGraph & TargetGraph, + Epetra_Import & Importer ); + + //! Constructs a Epetra_OffsetIndex object from the graphs and an exporter. + Epetra_OffsetIndex( const Epetra_CrsGraph & SourceGraph, + const Epetra_CrsGraph & TargetGraph, + Epetra_Export & Exporter ); + + //! Epetra_OffsetIndex copy constructor. + Epetra_OffsetIndex(const Epetra_OffsetIndex & Indexor); + + //! Epetra_OffsetIndex destructor. + virtual ~Epetra_OffsetIndex(void); + + //! @name Print object to an output stream + //@{ + virtual void Print(ostream & os) const; + //@} + + //! Accessor + int ** SameOffsets() const { return SameOffsets_; } + + //! Accessor + int ** PermuteOffsets() const { return PermuteOffsets_; } + + //! Accessor + int ** RemoteOffsets() const { return RemoteOffsets_; } + + private: + + void GenerateLocalOffsets_( const Epetra_CrsGraph & SourceGraph, + const Epetra_CrsGraph & TargetGraph, + const int * PermuteLIDs ); + + void GenerateRemoteOffsets_( const Epetra_CrsGraph & SourceGraph, + const Epetra_CrsGraph & TargetGraph, + const int * ExportLIDs, + const int * RemoteLIDs, + Epetra_Distributor & Distor ); + + //! Epetra_OffsetIndex copy constructor. + Epetra_OffsetIndex & operator=(const Epetra_OffsetIndex & Indexor); + public: + + int NumSame_; + int ** SameOffsets_; + int NumPermute_; + int ** PermuteOffsets_; + int NumExport_; + int NumRemote_; + int ** RemoteOffsets_; + + bool DataOwned_; +}; + +#endif /* EPETRA_OFFSETINDEX_H */ diff --git a/fastlib/trilinos/include/Epetra_Operator.h b/fastlib/trilinos/include/Epetra_Operator.h new file mode 100644 index 0000000000..2a715abf28 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Operator.h @@ -0,0 +1,134 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_OPERATOR_H +#define EPETRA_OPERATOR_H + +class Epetra_MultiVector; +class Epetra_Map; +class Epetra_Comm; + +//! Epetra_Operator: A pure virtual class for using real-valued double-precision operators. +/*! The Epetra_Operator class is a pure virtual class (specifies interface only) that + enable the use of real-valued double-precision operators. It is currently implemented by both the + Epetra_CrsMatrix and Epetra_VbrMatrix classes and the Ifpack_CrsRiluk preconditioner class. + + +*/ + +class Epetra_Operator { + + public: + + //! @name Destructor + //@{ + //! Destructor + virtual ~Epetra_Operator() {}; + //@} + + //! @name Atribute set methods + //@{ + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param In + UseTranspose -If true, multiply by the transpose of operator, otherwise just use operator. + + \return Integer error code, set to 0 if successful. Set to -1 if this implementation does not support transpose. + */ + virtual int SetUseTranspose(bool UseTranspose) = 0; + //@} + + //! @name Mathematical functions + //@{ + + //! Returns the result of a Epetra_Operator applied to a Epetra_MultiVector X in Y. + /*! + \param In + X - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const = 0; + + //! Returns the result of a Epetra_Operator inverse applied to an Epetra_MultiVector X in Y. + /*! + \param In + X - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + + \warning In order to work with AztecOO, any implementation of this method must + support the case where X and Y are the same object. + */ + virtual int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const = 0; + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f]. + + \warning This method must not be called unless HasNormInf() returns true. + */ + virtual double NormInf() const = 0; + //@} + + //! @name Atribute access functions + //@{ + + //! Returns a character string describing the operator + virtual const char * Label() const = 0; + + //! Returns the current UseTranspose setting. + virtual bool UseTranspose() const = 0; + + //! Returns true if the \e this object can provide an approximate Inf-norm, false otherwise. + virtual bool HasNormInf() const = 0; + + //! Returns a pointer to the Epetra_Comm communicator associated with this operator. + virtual const Epetra_Comm & Comm() const = 0; + + //! Returns the Epetra_Map object associated with the domain of this operator. + virtual const Epetra_Map & OperatorDomainMap() const = 0; + + //! Returns the Epetra_Map object associated with the range of this operator. + virtual const Epetra_Map & OperatorRangeMap() const = 0; + //@} + +}; + +#endif /* EPETRA_OPERATOR_H */ diff --git a/fastlib/trilinos/include/Epetra_RowMatrix.h b/fastlib/trilinos/include/Epetra_RowMatrix.h new file mode 100644 index 0000000000..3478a85285 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_RowMatrix.h @@ -0,0 +1,257 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_ROWMATRIX_H +#define EPETRA_ROWMATRIX_H + +class Epetra_Comm; +class Epetra_Import; +class Epetra_Export; +class Epetra_Vector; +class Epetra_MultiVector; +#include "Epetra_Operator.h" +#include "Epetra_SrcDistObject.h" + + +//! Epetra_RowMatrix: A pure virtual class for using real-valued double-precision row matrices. + +/*! The Epetra_RowMatrix class is a pure virtual class (specifies interface only) that + enable the use of real-valued double-precision sparse matrices + where matrix entries are intended for row access. It is currently implemented by both the + Epetra_CrsMatrix and Epetra_VbrMatrix classes. + + +*/ + + +class Epetra_RowMatrix: public virtual Epetra_Operator, public virtual Epetra_SrcDistObject { + + public: + //! @name Destructor + //@{ + //! Destructor + virtual ~Epetra_RowMatrix() {}; + + //@} + + //! @name Matrix data extraction routines + //@{ + + //! Returns the number of nonzero entries in MyRow. + /*! + \param In + MyRow - Local row. + \param Out + NumEntries - Number of nonzero values present. + + \return Integer error code, set to 0 if successful. + */ + virtual int NumMyRowEntries(int MyRow, int & NumEntries) const = 0; + + + //! Returns the maximum of NumMyRowEntries() over all rows. + virtual int MaxNumEntries() const = 0; + + //! Returns a copy of the specified local row in user-provided arrays. + /*! + \param In + MyRow - Local row to extract. + \param In + Length - Length of Values and Indices. + \param Out + NumEntries - Number of nonzero entries extracted. + \param Out + Values - Extracted values for this row. + \param Out + Indices - Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. + */ + virtual int ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, double *Values, int * Indices) const = 0; + + //! Returns a copy of the main diagonal in a user-provided vector. + /*! + \param Out + Diagonal - Extracted main diagonal. + + \return Integer error code, set to 0 if successful. + */ + virtual int ExtractDiagonalCopy(Epetra_Vector & Diagonal) const = 0; + //@} + + //! @name Mathematical functions + //@{ + + //! Returns the result of a Epetra_RowMatrix multiplied by a Epetra_MultiVector X in Y. + /*! + \param In + TransA -If true, multiply by the transpose of matrix, otherwise just use matrix. + \param In + X - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Out + Y -A Epetra_MultiVector of dimension NumVectorscontaining result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const = 0; + + //! Returns result of a local-only solve using a triangular Epetra_RowMatrix with Epetra_MultiVectors X and Y. + /*! This method will perform a triangular solve independently on each processor of the parallel machine. + No communication is performed. + \param In + Upper -If true, solve Ux = y, otherwise solve Lx = y. + \param In + Trans -If true, solve transpose problem. + \param In + UnitDiagonal -If true, assume diagonal is unit (whether it's stored or not). + \param In + X - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_MultiVector& X, + Epetra_MultiVector& Y) const = 0; + + //! Computes the sum of absolute values of the rows of the Epetra_RowMatrix, results returned in x. + /*! The vector x will return such that x[i] will contain the inverse of sum of the absolute values of the + \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. Using the resulting vector from this function as input to LeftScale() + will make the infinity norm of the resulting matrix exactly 1. + \param Out + x -A Epetra_Vector containing the row sums of the \e this matrix. + \warning It is assumed that the distribution of x is the same as the rows of \e this. + + \return Integer error code, set to 0 if successful. + */ + virtual int InvRowSums(Epetra_Vector& x) const = 0; + + //! Scales the Epetra_RowMatrix on the left with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the row number of A + and j denotes the column number of A. + \param In + x -A Epetra_Vector to solve for. + + \return Integer error code, set to 0 if successful. + */ + virtual int LeftScale(const Epetra_Vector& x) = 0; + + //! Computes the sum of absolute values of the columns of the Epetra_RowMatrix, results returned in x. + /*! The vector x will return such that x[j] will contain the inverse of sum of the absolute values of the + \e this matrix will be sca such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. Using the resulting vector from this function as input to + RighttScale() will make the one norm of the resulting matrix exactly 1. + \param Out + x -A Epetra_Vector containing the column sums of the \e this matrix. + \warning It is assumed that the distribution of x is the same as the rows of \e this. + + \return Integer error code, set to 0 if successful. + */ + virtual int InvColSums(Epetra_Vector& x) const = 0; + + //! Scales the Epetra_RowMatrix on the right with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. + \param In + x -The Epetra_Vector used for scaling \e this. + + \return Integer error code, set to 0 if successful. + */ + virtual int RightScale(const Epetra_Vector& x) = 0; + //@} + + //! @name Atribute access functions + //@{ + + //! If FillComplete() has been called, this query returns true, otherwise it returns false. + virtual bool Filled() const = 0; + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\len} \sum_{i=1}^m |a_{ij}| \f]. + */ + virtual double NormInf() const = 0; + + //! Returns the one norm of the global matrix. + /* Returns the quantity \f$ \| A \|_1\f$ such that + \f[\| A \|_1= \max_{1\lej\len} \sum_{j=1}^n |a_{ij}| \f]. + */ + virtual double NormOne() const = 0; + + //! Returns the number of nonzero entries in the global matrix. + /* + Note that depending on the matrix implementation, it is sometimes + possible to have some nonzeros that appear on multiple processors. + In that case, those nonzeros may be counted multiple times (also + depending on the matrix implementation). + */ + virtual int NumGlobalNonzeros() const = 0; + + //! Returns the number of global matrix rows. + virtual int NumGlobalRows() const = 0; + + //! Returns the number of global matrix columns. + virtual int NumGlobalCols() const= 0; + + //! Returns the number of global nonzero diagonal entries, based on global row/column index comparisons. + virtual int NumGlobalDiagonals() const = 0; + + //! Returns the number of nonzero entries in the calling processor's portion of the matrix. + virtual int NumMyNonzeros() const = 0; + + //! Returns the number of matrix rows owned by the calling processor. + virtual int NumMyRows() const = 0; + + //! Returns the number of matrix columns owned by the calling processor. + virtual int NumMyCols() const = 0; + + //! Returns the number of local nonzero diagonal entries, based on global row/column index comparisons. + virtual int NumMyDiagonals() const = 0; + + //! If matrix is lower triangular in local index space, this query returns true, otherwise it returns false. + virtual bool LowerTriangular() const = 0; + + //! If matrix is upper triangular in local index space, this query returns true, otherwise it returns false. + virtual bool UpperTriangular() const = 0; + + //! Returns the Epetra_Map object associated with the rows of this matrix. + virtual const Epetra_Map & RowMatrixRowMap() const = 0; + + //! Returns the Epetra_Map object associated with the columns of this matrix. + virtual const Epetra_Map & RowMatrixColMap() const = 0; + + //! Returns the Epetra_Import object that contains the import operations for distributed operations. + virtual const Epetra_Import * RowMatrixImporter() const = 0; + //@} +}; + +#endif /* EPETRA_ROWMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_RowMatrixTransposer.h b/fastlib/trilinos/include/Epetra_RowMatrixTransposer.h new file mode 100644 index 0000000000..00e687a494 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_RowMatrixTransposer.h @@ -0,0 +1,154 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_CRSMATRIXTRANSPOSER_H +#define EPETRA_CRSMATRIXTRANSPOSER_H +#include +class Epetra_RowMatrix; +class Epetra_CrsMatrix; +class Epetra_Map; +class Epetra_Export; + +//! Epetra_RowMatrixTransposer: A class for transposing an Epetra_RowMatrix object. + +/*! This class provides capabilities to construct a transpose matrix of an existing Epetra_RowMatrix + object and (optionally) redistribute it across a parallel distributed memory machine. +*/ + +class Epetra_RowMatrixTransposer { + + public: + + //! @name Constructors/destructors + //@{ + //! Primary Epetra_RowMatrixTransposer constructor. + /*! + \param Matrix (In) An existing Epetra_RowMatrix object. The Epetra_RowMatrix, the LHS and RHS pointers + do not need to be defined before this constructor is called. + + \return Pointer to a Epetra_RowMatrixTransposer object. + + */ + Epetra_RowMatrixTransposer(Epetra_RowMatrix * OrigMatrix); + + //! Epetra_RowMatrixTransposer copy constructor. + + Epetra_RowMatrixTransposer(const Epetra_RowMatrixTransposer& Source); + + //! Epetra_RowMatrixTransposer destructor. + + virtual ~Epetra_RowMatrixTransposer(); + //@} + + //! @name Forward transformation methods + //@{ + + //! Generate a new Epetra_CrsMatrix as the transpose of an Epetra_RowMatrix passed into the constructor. + /*! Constructs a new Epetra_CrsMatrix that is a copy of the Epetra_RowMatrix passed in to the constructor. + + \param MakeDataContiguous (In) Causes the output matrix, LHS and RHS to be stored in a form compatible with + Fortran-style solvers. The output matrix will be compatible with the Harwell-Boeing compressed + column format. The RHS and LHS will be stored such that the last value in column j of the + multivector is stored next to the first value in column j+1. + \param TransposeRowMap (Optional/In) If this argument is defined, the transpose matrix will be distributed + using this map as the row map for the transpose. If it is set to zero, the transpose matrix will use + the OrigMatrix->RowMatrixDomainMap as the row map. + + \return Integer error code, 0 if no errors. Negative if some fatal error occured. + + */ + int CreateTranspose(const bool MakeDataContiguous, + Epetra_CrsMatrix *& TransposeMatrix, + Epetra_Map * TransposeRowMap = 0); + + + //! Update the values of an already-redistributed problem. + /*! Updates the values of an already-redistributed problem. This method allows updating + the redistributed problem without + allocating new storage. + + \param MatrixWithNewValues (In) The values from MatrixWithNewValues will be copied into the TransposeMatrix. The + MatrixWithNewValues object must be identical in structure to the original matrix object used to create + this instance of Epetra_RowMatrixTransposer. + + \return Integer error code, 0 if no errors. Negative if some fatal error occured. + + */ + int UpdateTransposeValues(Epetra_RowMatrix * MatrixWithNewValues); + //@} + + //! @name Reverse transformation methods + //@{ + //! Update values of original matrix (Not implemented and not sure if we will implement this). + int UpdateOriginalMatrixValues(); + //@} + + //! @name Attribute accessor methods + //@{ + + //! Returns const reference to the Epetra_Map object describing the row distribution of the transpose matrix. + /*! The RedistExporter object can be used to redistribute other Epetra_DistObject objects whose maps are compatible with + the original linear problem map, or with the RedistMap(). + \warning Must not be called before CreateTranspose()is called. + */ + const Epetra_Map & TransposeRowMap() const {return(*TransposeRowMap_);}; + //! Returns const reference to the Epetra_Export object used to redistribute the original matrix. + /*! The TransposeExporter object can be used to redistribute other Epetra_DistObject objects whose maps are compatible with + the original matrix. + \warning Must not be called before CreateTranspose() is called. + */ + const Epetra_Export & TransposeExporter() const{return(*TransposeExporter_);}; + //@} + + private: + void DeleteData(); + Epetra_RowMatrixTransposer& operator=(const Epetra_RowMatrixTransposer& src); + + Epetra_RowMatrix * OrigMatrix_; + Epetra_CrsMatrix * TransposeMatrix_; + Epetra_Export * TransposeExporter_; + Epetra_Map * TransposeRowMap_; + bool TransposeCreated_; + bool MakeDataContiguous_; + int NumMyRows_; + int NumMyCols_; + int MaxNumEntries_; + int * Indices_; + double * Values_; + int * TransNumNz_; + int ** TransIndices_; + double ** TransValues_; + int * TransMyGlobalEquations_; + bool OrigMatrixIsCrsMatrix_; + +}; + +#endif /* EPETRA_CRSMATRIXTRANSPOSER_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialComm.h b/fastlib/trilinos/include/Epetra_SerialComm.h new file mode 100644 index 0000000000..432c375147 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialComm.h @@ -0,0 +1,380 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALCOMM_H +#define EPETRA_SERIALCOMM_H + +#include "Epetra_Object.h" +#include "Epetra_Comm.h" +#include "Epetra_SerialCommData.h" +class Epetra_Distributor; + +//! Epetra_SerialComm: The Epetra Serial Communication Class. +/*! The Epetra_SerialComm class is an implementation of Epetra_Comm, providing the general + information and services needed for other Epetra classes to run on a serial computer. +*/ + +class Epetra_SerialComm: public Epetra_Object, public virtual Epetra_Comm { + + public: + //! @name Constructor/Destructor Methods + //@{ + + //! Epetra_SerialComm Serial Constructor. + /*! Builds an instance of a serial communicator. Even + if the application is running in parallel via MPI, this communicator + will execute in serial. The access functions return the number of + processors to be 1 and the processor ID to be 0. + */ + Epetra_SerialComm(); + + + //! Epetra_SerialComm Copy Constructor. + /*! Makes an exact copy of an existing Epetra_SerialComm instance. + */ + Epetra_SerialComm(const Epetra_SerialComm& Comm); + + //! Clone method. + Epetra_Comm * Clone() const { + return(dynamic_cast(new Epetra_SerialComm(*this))); + }; + + //! Epetra_SerialComm Destructor. + /*! Completely deletes a Epetra_SerialComm object. + \warning Note: All objects that depend + on a Epetra_SerialComm instance should be destroyed prior to calling this + function. + */ + virtual ~Epetra_SerialComm(); + //@} + + //! @name Barrier Methods + //@{ + //! Epetra_SerialComm Barrier function. + /*! A no-op for a serial communicator. + */ + void Barrier() const; + //@} + + //! @name Broadcast Methods + //@{ + //! Epetra_SerialComm Broadcast function. + /*! A no-op for a serial communicator. + \param MyVals InOut + On entry, the root processor contains the list of values. On exit, + all processors will have the same list of values. Note that values must be + allocated on all processor before the broadcast. + \param Count In + On entry, contains the length of the list of MyVals. + \param Root In + On entry, contains the processor from which all processors will receive a copy of MyVals. + */ + + int Broadcast(double * MyVals, int Count, int Root) const; + + //! Epetra_SerialComm Broadcast function. + /*! A no-op for a serial communicator. + \param MyVals InOut + On entry, the root processor contains the list of values. On exit, + all processors will have the same list of values. Note that values must be + allocated on all processor before the broadcast. + \param Count In + On entry, contains the length of the list of MyVals. + \param Root In + On entry, contains the processor from which all processors will receive a copy of MyVals. + */ + + int Broadcast(int * MyVals, int Count, int Root) const; + + //! Epetra_SerialComm Broadcast function. + /*! A no-op for a serial communicator. + \param MyVals InOut + On entry, the root processor contains the list of values. On exit, + all processors will have the same list of values. Note that values must be + allocated on all processor before the broadcast. + \param Count In + On entry, contains the length of the list of MyVals. + \param Root In + On entry, contains the processor from which all processors will receive a copy of MyVals. + */ + + int Broadcast(long * MyVals, int Count, int Root) const; + //@} + + //! @name Gather Methods + //@{ + //! Epetra_SerialComm All Gather function. + /*! A copy for a serial communicator. + \param MyVals In + On entry, contains the list of values, to be sent to all processors. + \param AllVals Out + On exit, contains the list of values from all processors. Must by of size NumProc*Count. + \param Count In + On entry, contains the length of the list of MyVals. + */ + + int GatherAll(double * MyVals, double * AllVals, int Count) const; + + //! Epetra_SerialComm All Gather function. + /*! A copy for a serial communicator. + \param MyVals In + On entry, contains the list of values, to be sent to all processors. + \param AllVals Out + On exit, contains the list of values from all processors. Must by of size NumProc*Count. + \param Count In + On entry, contains the length of the list of MyVals. + */ + + int GatherAll(int * MyVals, int * AllVals, int Count) const; + + //! Epetra_SerialComm All Gather function. + /*! A copy for a serial communicator. + \param MyVals In + On entry, contains the list of values, to be sent to all processors. + \param AllVals Out + On exit, contains the list of values from all processors. Must by of size NumProc*Count. + \param Count In + On entry, contains the length of the list of MyVals. + */ + + int GatherAll(long * MyVals, long * AllVals, int Count) const; + //@} + + //! @name Sum Methods + //@{ + //! Epetra_SerialComm Global Sum function. + /*! A copy for a serial communicator. + \param PartialSums In + On entry, contains the list of values, usually partial sums computed locally, + to be summed across all processors. + \param GlobalSums Out + On exit, contains the list of values summed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + + int SumAll(double * PartialSums, double * GlobalSums, int Count) const; + + //! Epetra_SerialComm Global Sum function. + /*! A copy for a serial communicator. + \param PartialSums In + On entry, contains the list of values, usually partial sums computed locally, + to be summed across all processors. + \param GlobalSums Out + On exit, contains the list of values summed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int SumAll(int * PartialSums, int * GlobalSums, int Count) const; + + //! Epetra_SerialComm Global Sum function. + /*! A copy for a serial communicator. + \param PartialSums In + On entry, contains the list of values, usually partial sums computed locally, + to be summed across all processors. + \param GlobalSums Out + On exit, contains the list of values summed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int SumAll(long * PartialSums, long * GlobalSums, int Count) const; + //@} + + //! @name Max/Min Methods + //@{ + //! Epetra_SerialComm Global Max function. + /*! A copy for a serial communicator. + \param PartialMaxs In + On entry, contains the list of values, usually partial maxs computed locally, + using these Partial Maxs, the max across all processors will be computed. + \param GlobalMaxs Out + On exit, contains the list of maxs computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int MaxAll(double * PartialMaxs, double * GlobalMaxs, int Count) const; + + //! Epetra_SerialComm Global Max function. + /*! A copy for a serial communicator. + \param PartialMaxs In + On entry, contains the list of values, usually partial maxs computed locally; + using these Partial Maxs, the max across all processors will be computed. + \param GlobalMaxs Out + On exit, contains the list of maxs computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int MaxAll(int * PartialMaxs, int * GlobalMaxs, int Count) const; + + //! Epetra_SerialComm Global Max function. + /*! A copy for a serial communicator. + \param PartialMaxs In + On entry, contains the list of values, usually partial maxs computed locally; + using these Partial Maxs, the max across all processors will be computed. + \param GlobalMaxs Out + On exit, contains the list of maxs computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int MaxAll(long * PartialMaxs, long * GlobalMaxs, int Count) const; + + //! Epetra_SerialComm Global Min function. + /*! A copy for a serial communicator. + \param PartialMins In + On entry, contains the list of values, usually partial mins computed locally; + using these Partial Mins, the min across all processors will be computed. + \param GlobalMins Out + On exit, contains the list of mins computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int MinAll(double * PartialMins, double * GlobalMins, int Count) const; + + //! Epetra_SerialComm Global Min function. + /*! A copy for a serial communicator. + \param PartialMins In + On entry, contains the list of values, usually partial mins computed locally; + using these Partial Mins, the min across all processors will be computed. + \param GlobalMins Out + On exit, contains the list of mins computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int MinAll(int * PartialMins, int * GlobalMins, int Count) const; + + //! Epetra_SerialComm Global Min function. + /*! A copy for a serial communicator. + \param PartialMins In + On entry, contains the list of values, usually partial mins computed locally; + using these Partial Mins, the min across all processors will be computed. + \param GlobalMins Out + On exit, contains the list of mins computed across all processors. + \param Count In + On entry, contains the length of the list of values. + */ + int MinAll(long * PartialMins, long * GlobalMins, int Count) const; + //@} + + //! @name Parallel Prefix Methods + //@{ + //! Epetra_SerialComm Scan Sum function. + /*! A copy for a serial communicator. + \param MyVals In + On entry, contains the list of values to be summed across all processors. + \param ScanSums Out + On exit, contains the list of values summed across processors 0 through i. + \param Count In + On entry, contains the length of the list of values. + */ + int ScanSum(double * MyVals, double * ScanSums, int Count) const; + + //! Epetra_SerialComm Scan Sum function. + /*! A copy for a serial communicator. + \param MyVals In + On entry, contains the list of values to be summed across all processors. + \param ScanSums Out + On exit, contains the list of values summed across processors 0 through i. + \param Count In + On entry, contains the length of the list of values. + */ + int ScanSum(int * MyVals, int * ScanSums, int Count) const; + + //! Epetra_SerialComm Scan Sum function. + /*! A copy for a serial communicator. + \param MyVals In + On entry, contains the list of values to be summed across all processors. + \param ScanSums Out + On exit, contains the list of values summed across processors 0 through i. + \param Count In + On entry, contains the length of the list of values. + */ + int ScanSum(long * MyVals, long * ScanSums, int Count) const; + //@} + + //! @name Attribute Accessor Methods + //@{ + + //! Return my process ID. + /*! In MPI mode returns the rank of the calling process. In serial mode + returns 0. + */ + int MyPID() const {return(SerialCommData_->MyPID_);}; + + //! Returns total number of processes (always returns 1 for SerialComm). + int NumProc() const {return(SerialCommData_->NumProc_);}; + + //@} + + //! @name Gather/Scatter and Directory Constructors + //@{ + //! Create a distributor object. + Epetra_Distributor * CreateDistributor() const; + //! Create a directory object for the given Epetra_BlockMap. + Epetra_Directory * CreateDirectory(const Epetra_BlockMap & Map) const; + //@} + + //! @name Print object to an output stream + //@{ + //! Print method that implements Epetra_Object virtual Print method + inline void Print(ostream & os) const { + os << "::Processor "<< MyPID()<<" of " << NumProc() << " total processors."; + return; + } + //! Print method that implements Epetra_Comm virtual PrintInfo method + void PrintInfo(ostream & os) const { + Epetra_SerialComm::Print(os); + return; + }; + //@} + + //! @name Expert Users and Developers Only + //@{ + + //! Returns the reference count of SerialCommData. + /*! (Intended for testing purposes.) */ + int ReferenceCount() const; + + //! Returns a pointer to the SerialCommData instance this SerialComm uses. + /*! (Intended for developer use only for testing purposes.) */ + const Epetra_SerialCommData * DataPtr() const {return(SerialCommData_);}; + + //@} + + //! Assignment Operator + Epetra_SerialComm & operator=(const Epetra_SerialComm & Comm); + + private: + + void CleanupData(); + Epetra_SerialCommData * SerialCommData_; + +}; +#endif /* EPETRA_SERIALCOMM_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialCommData.h b/fastlib/trilinos/include/Epetra_SerialCommData.h new file mode 100644 index 0000000000..7d8605aee4 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialCommData.h @@ -0,0 +1,65 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALCOMMDATA_H +#define EPETRA_SERIALCOMMDATA_H + +#include "Epetra_Data.h" + +//! Epetra_SerialCommData: The Epetra Serial Communication Data Class. +/*! The Epetra_SerialCommData class is an implementation detail of Epetra_SerialComm. + It is reference-counted, and can be shared by multiple Epetra_SerialComm instances. + It derives from Epetra_Data, and inherits reference-counting from it. +*/ + +class Epetra_SerialCommData : public Epetra_Data { + friend class Epetra_SerialComm; + private: + //! @name Constructor/Destructor Methods + //@{ + + //! Epetra_SerialCommData Default Constructor. + Epetra_SerialCommData(); + + //! Epetra_SerialCommData Destructor. + ~Epetra_SerialCommData(); + + //@} + + int MyPID_; + int NumProc_; + + // these are intentionally declared but not defined. See Epetra Developer's Guide for details. + Epetra_SerialCommData(const Epetra_SerialCommData & CommData); + Epetra_SerialCommData& operator=(const Epetra_SerialCommData & CommData); + +}; +#endif /* EPETRA_SERIALCOMMDATA_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialDenseMatrix.h b/fastlib/trilinos/include/Epetra_SerialDenseMatrix.h new file mode 100644 index 0000000000..1d1c90d871 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialDenseMatrix.h @@ -0,0 +1,529 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALDENSEMATRIX_H +#define EPETRA_SERIALDENSEMATRIX_H + +#include "Epetra_Object.h" +#include "Epetra_CompObject.h" +#include "Epetra_BLAS.h" +#include "Epetra_SerialDenseOperator.h" +class Epetra_SerialSymDenseMatrix; +class Epetra_VbrMatrix; + +//! Epetra_SerialDenseMatrix: A class for constructing and using real double precision general dense matrices. + +/*! The Epetra_SerialDenseMatrix class enables the construction and use of real-valued, general, + double-precision dense matrices. It is built on the BLAS, and derives from the Epetra_BLAS. + +The Epetra_SerialDenseMatrix class is intended to provide very basic support for dense rectangular matrices. + + +Constructing Epetra_SerialDenseMatrix Objects + +There are four Epetra_SerialDenseMatrix constructors. The first constructs a zero-sized object which should be made +to appropriate length using the Shape() or Reshape() functions and then filled with the [] or () operators. +The second constructs an object sized to the dimensions specified, which should be filled with the [] or () operators. +The third is a constructor that accepts user +data as a 2D array, and the fourth is a copy constructor. The third constructor has +two data access modes (specified by the Epetra_DataAccess argument): +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the object. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +Extracting Data from Epetra_SerialDenseMatrix Objects + +Once a Epetra_SerialDenseMatrix is constructed, it is possible to view the data via access functions. + +\warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective. + + +Vector and Utility Functions + +Once a Epetra_SerialDenseMatrix is constructed, several mathematical functions can be applied to +the object. Specifically: +
      +
    • Multiplication. +
    • Norms. +
    + +Counting floating point operations +The Epetra_SerialDenseMatrix class has Epetra_CompObject as a base class. Thus, floating point operations +are counted and accumulated in the Epetra_Flop object (if any) that was set using the SetFlopCounter() +method in the Epetra_CompObject base class. + +*/ + + +//========================================================================= +class Epetra_SerialDenseMatrix : public Epetra_CompObject, public Epetra_Object, public Epetra_SerialDenseOperator, public Epetra_BLAS { + + public: + + //! @name Constructor/Destructor Methods + //@{ + //! Default constructor; defines a zero size object. + /*! + Epetra_SerialDenseMatrix objects defined by the default constructor should be sized with the + Shape() or Reshape functions. + Values should be defined by using the [] or () operators. + */ + Epetra_SerialDenseMatrix(bool set_object_label=true); + + //! Shaped constructor; defines a variable-sized object + /*! + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + Epetra_SerialDenseMatrix objects defined by the shaped constructor are already shaped to the + dimensions given as a parameters. All values are initialized to 0. Calling this constructor + is equivalent to using the default constructor, and then calling the Shape function on it. + Values should be defined by using the [] or () operators. + */ + Epetra_SerialDenseMatrix(int NumRows, int NumCols, bool set_object_label=true); + + //! Set object values from two-dimensional array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + A - Pointer to an array of double precision numbers. The first vector starts at A. + The second vector starts at A+LDA, the third at A+2*LDA, and so on. + \param In + LDA - The "Leading Dimension", or stride between vectors in memory. + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + See Detailed Description section for further discussion. + */ + Epetra_SerialDenseMatrix(Epetra_DataAccess CV, double* A, int LDA, int NumRows, int NumCols, + bool set_object_label=true); + + //! Epetra_SerialDenseMatrix copy constructor. + + Epetra_SerialDenseMatrix(const Epetra_SerialDenseMatrix& Source); + + //! Epetra_SerialDenseMatrix destructor. + virtual ~Epetra_SerialDenseMatrix (); + //@} + + //! @name Shaping/sizing Methods + //@{ + //! Set dimensions of a Epetra_SerialDenseMatrix object; init values to zero. + /*! + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + Allows user to define the dimensions of a Epetra_SerialDenseMatrix at any point. This function can + be called at any point after construction. Any values that were previously in this object are + destroyed and the resized matrix starts off with all zero values. + + \return Integer error code, set to 0 if successful. + */ + int Shape(int NumRows, int NumCols); + + //! Reshape a Epetra_SerialDenseMatrix object. + /*! + \param In + NumRows - Number of rows in object. + \param In + NumCols - Number of columns in object. + + Allows user to define the dimensions of a Epetra_SerialDenseMatrix at any point. This function can + be called at any point after construction. Any values that were previously in this object are + copied into the new shape. If the new shape is smaller than the original, the upper left portion + of the original matrix (the principal submatrix) is copied to the new matrix. + + \return Integer error code, set to 0 if successful. + */ + int Reshape(int NumRows, int NumCols); + //@} + + //! @name Mathematical methods + //@{ + + //! Matrix-Matrix multiplication, \e this = ScalarThis*\e this + ScalarAB*A*B. + /*! This function performs a variety of matrix-matrix multiply operations. + + \param In + TransA - Operate with the transpose of A if = 'T', else no transpose if = 'N'. + \param In + TransB - Operate with the transpose of B if = 'T', else no transpose if = 'N'. + + \param In + ScalarAB - Scalar to multiply with A*B. + \param In + A - Dense Matrix. + \param In + B - Dense Matrix. + \param In + ScalarThis - Scalar to multiply with \e this. + + \return Integer error code, set to 0 if successful. + + */ + int Multiply(char TransA, char TransB, double ScalarAB, + const Epetra_SerialDenseMatrix& A, + const Epetra_SerialDenseMatrix& B, + double ScalarThis); + + //! Matrix-Vector multiplication, y = A*x, where 'this' == A. + /* This method is intended to imitate the semantics of the matrix-vector + multiplication provided by Epetra's sparse matrices. The 'vector' arguments + are actually matrices; this method will return an error if the + dimensions of 'x' are not compatible. 'y' will be reshaped if necessary. + */ + int Multiply(bool transA, + const Epetra_SerialDenseMatrix& x, + Epetra_SerialDenseMatrix& y); + + //! Matrix-Matrix multiplication with a symmetric matrix A. + /*! If SideA = 'L', compute \e this = ScalarThis*\e this + ScalarAB*A*B. + If SideA = 'R', compute \e this = ScalarThis*\e this + ScalarAB*B*A. + +This function performs a variety of matrix-matrix multiply operations. + + \param In + SideA - Specifies order of A relative to B. + + \param In + ScalarAB - Scalar to multiply with A*B. + \param In + A - Symmetric Dense Matrix, either upper or lower triangle will be used depending on + value of A.Upper(). + \param In + B - Dense Matrix. + \param In + ScalarThis - Scalar to multiply with \e this. + + \return Integer error code, set to 0 if successful. + + */ + int Multiply(char SideA, double ScalarAB, + const Epetra_SerialSymDenseMatrix& A, + const Epetra_SerialDenseMatrix& B, + double ScalarThis); + + //! Inplace scalar-matrix product A = \e a A. + /*! Scale a matrix, entry-by-entry using the value ScalarA. + + + \param ScalarA (In) Scalar to multiply with A. + + \return Integer error code, set to 0 if successful. + + */ + int Scale(double ScalarA); + + //! Computes the 1-Norm of the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. + */ + virtual double NormOne() const; + + //! Computes the Infinity-Norm of the \e this matrix. + virtual double NormInf() const; + + //@} + + //! @name Data Accessor methods + //@{ + + //! Value copy from one matrix to another. + /*! + The operator= allows one to copy the values from one existing SerialDenseMatrix to another, as + long as there is enough room in the target to hold the source. + + \return Values of the left hand side matrix are modified by the values of the right hand side matrix. + */ + Epetra_SerialDenseMatrix & operator = (const Epetra_SerialDenseMatrix& Source); + + //! Comparison operator. + /*! operator== compares two Epetra_SerialDenseMatrix objects, returns false if sizes are different, + or if any coefficients differ by an amount greater than Epetra_MinDouble. + */ + bool operator==(const Epetra_SerialDenseMatrix& rhs) const; + + //! Inequality operator + /*! operator!= simply returns the negation of operator==. + */ + bool operator!=(const Epetra_SerialDenseMatrix& rhs) const + { return !(*this == rhs); } + + //! Add one matrix to another. + /*! + The operator+= allows one to add the values from one existin SerialDenseMatrix to another, as + long as there is enough room in the target to hold the source. + + \return Values of the left hand side matrix are modified by the addition + of the values of the right hand side matrix. + */ + Epetra_SerialDenseMatrix & operator += (const Epetra_SerialDenseMatrix& Source); + + //! Element access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Element from the specified row and column. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + double& operator () (int RowIndex, int ColIndex); + + //! Element access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Element from the specified row and column. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const double& operator () (int RowIndex, int ColIndex) const; + + //! Column access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Pointer to address of specified column. + + \warning No bounds checking can be done for the index i in the expression A[j][i]. + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + double* operator [] (int ColIndex); + + //! Column access function. + /*! + The parentheses operator returns the element in the ith row and jth column if A(i,j) is + specified, the expression A[j][i] (note that i and j are reversed) will return the same element. + Thus, A(i,j) = A[j][i] for all valid i and j. + + \return Pointer to address of specified column. + + \warning No bounds checking can be done for the index i in the expression A[j][i]. + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const double* operator [] (int ColIndex) const; + + //! Set matrix values to random numbers. + /*! + SerialDenseMatrix uses the random number generator provided by Epetra_Util. + The matrix values will be set to random values on the interval (-1.0, 1.0). + + \return Integer error code, set to 0 if successful. + */ + int Random(); + + //! Returns row dimension of system. + int M() const {return(M_);}; + + //! Returns column dimension of system. + int N() const {return(N_);}; + + //! Returns pointer to the \e this matrix. + double* A() const {return(A_);}; + + //! Returns pointer to the \e this matrix. + double* A() {return(A_);}; + + //! Returns the leading dimension of the \e this matrix. + int LDA() const {return(LDA_);}; + + //! Returns the data access mode of the \e this matrix. + Epetra_DataAccess CV() const {return(CV_);}; + //@} + + //! @name I/O methods + //@{ + //! Print service methods; defines behavior of ostream << operator. + virtual void Print(ostream& os) const; + //@} + + //! @name Deprecated methods (will be removed in later versions of this class) + //@{ + + //! Computes the 1-Norm of the \e this matrix (identical to NormOne() method). + /*! + \return Integer error code, set to 0 if successful. + */ + virtual double OneNorm() const {return(NormOne());}; + + //! Computes the Infinity-Norm of the \e this matrix (identical to NormInf() method). + virtual double InfNorm() const {return(NormInf());}; + //@} + + //! @name Additional methods to support Epetra_SerialDenseOperator interface + //@{ + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param In + UseTranspose -If true, multiply by the transpose of operator, otherwise just use operator. + + \return Integer error code, set to 0 if successful. Set to -1 if this implementation does not support transpose. + */ + virtual int SetUseTranspose(bool UseTranspose) { UseTranspose_ = UseTranspose; return (0); } + + //! Returns the result of a Epetra_SerialDenseOperator applied to a Epetra_SerialDenseMatrix X in Y. + /*! + \param In + X - A Epetra_SerialDenseMatrix to multiply with operator. + \param Out + Y -A Epetra_SerialDenseMatrix containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Apply(const Epetra_SerialDenseMatrix& X, Epetra_SerialDenseMatrix& Y); + + //! Returns the result of a Epetra_SerialDenseOperator inverse applied to an Epetra_SerialDenseMatrix X in Y. + /*! + \param In + X - A Epetra_SerialDenseMatrix to solve for. + \param Out + Y -A Epetra_SerialDenseMatrix containing result. + + \return Integer error code, set to 0 if successful. + + */ + virtual int ApplyInverse(const Epetra_SerialDenseMatrix & X, Epetra_SerialDenseMatrix & Y) + { + (void)X;//prevents unused variable compiler warning + (void)Y; + return (-1); + } + + //! Returns a character string describing the operator + virtual const char * Label() const { return Epetra_Object::Label(); } + + //! Returns the current UseTranspose setting. + virtual bool UseTranspose() const { return UseTranspose_; } + + //! Returns true if the \e this object can provide an approximate Inf-norm, false otherwise. + virtual bool HasNormInf() const { return true; } + + //! Returns the row dimension of operator + virtual int RowDim() const { return M(); } + + //! Returns the column dimension of operator + virtual int ColDim() const { return N(); } + //@} + + protected: + + void CopyMat(double* Source, int Source_LDA, int NumRows, int NumCols, + double* Target, int Target_LDA, bool add=false); + void CleanupData(); + + int M_; + int N_; + bool A_Copied_; + Epetra_DataAccess CV_; + + //For performance reasons, it's better if Epetra_VbrMatrix can access the + //LDA_ and A_ members of this class directly without going through an + //accessor method. Rather than making them public members, we'll make + //Epetra_VbrMatrix a friend class. + + friend class Epetra_VbrMatrix; + + int LDA_; + double* A_; + + bool UseTranspose_; +}; + +// inlined definitions of op() and op[] +//========================================================================= +inline double& Epetra_SerialDenseMatrix::operator () (int RowIndex, int ColIndex) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (RowIndex >= M_ || RowIndex < 0) + throw ReportError("Row index = " +toString(RowIndex) + + " Out of Range 0 - " + toString(M_-1),-1); + if (ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " +toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_[ColIndex*LDA_ + RowIndex]); +} +//========================================================================= +inline const double& Epetra_SerialDenseMatrix::operator () (int RowIndex, int ColIndex) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (RowIndex >= M_ || RowIndex < 0) + throw ReportError("Row index = " +toString(RowIndex) + + " Out of Range 0 - " + toString(M_-1),-1); + if (ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " +toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_[ColIndex*LDA_ + RowIndex]); +} +//========================================================================= +inline double* Epetra_SerialDenseMatrix::operator [] (int ColIndex) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " +toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_ + ColIndex*LDA_); +} +//========================================================================= +inline const double* Epetra_SerialDenseMatrix::operator [] (int ColIndex) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (ColIndex >= N_ || ColIndex < 0) + throw ReportError("Column index = " +toString(ColIndex) + + " Out of Range 0 - " + toString(N_-1),-2); +#endif + return(A_+ ColIndex*LDA_); +} +//========================================================================= + +#endif /* EPETRA_SERIALDENSEMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialDenseOperator.h b/fastlib/trilinos/include/Epetra_SerialDenseOperator.h new file mode 100644 index 0000000000..014adcbea1 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialDenseOperator.h @@ -0,0 +1,120 @@ + +/* Copyright (2001) Sandia Corportation. Under the terms of Contract + * DE-AC04-94AL85000, there is a non-exclusive license for use of this + * work by or on behalf of the U.S. Government. Export of this program + * may require a license from the United States Government. */ + + +/* NOTICE: The United States Government is granted for itself and others + * acting on its behalf a paid-up, nonexclusive, irrevocable worldwide + * license in ths data to reproduce, prepare derivative works, and + * perform publicly and display publicly. Beginning five (5) years from + * July 25, 2001, the United States Government is granted for itself and + * others acting on its behalf a paid-up, nonexclusive, irrevocable + * worldwide license in this data to reproduce, prepare derivative works, + * distribute copies to the public, perform publicly and display + * publicly, and to permit others to do so. + * + * NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT + * OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES + * ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR + * RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY + * INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS + * THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. */ + +#ifndef _EPETRA_SERIALDENSEOPERATOR_H_ +#define _EPETRA_SERIALDENSEOPERATOR_H_ + +class Epetra_SerialDenseMatrix; + +//! Epetra_SerialDenseOperator: A pure virtual class for using real-valued double-precision operators. +/*! The Epetra_SerialDenseOperator class is a pure virtual class (specifies interface only) that + enable the use of real-valued double-precision operators. It is currently implemented by the + Epetra_SerialDenseMatrix, Epetra_SerialDenseSolver and Epetra_SerialDenseSVD classes. + + +*/ + +class Epetra_SerialDenseOperator { + + public: + + //! @name Destructor + //@{ + //! Destructor + virtual ~Epetra_SerialDenseOperator() {}; + //@} + + //! @name Atribute set methods + //@{ + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param In + UseTranspose -If true, multiply by the transpose of operator, otherwise just use operator. + + \return Integer error code, set to 0 if successful. Set to -1 if this implementation does not support transpose. + */ + virtual int SetUseTranspose(bool UseTranspose) = 0; + //@} + + //! @name Mathematical functions + //@{ + + //! Returns the result of a Epetra_SerialDenseOperator applied to a Epetra_SerialDenseMatrix X in Y. + /*! + \param In + X - A Epetra_SerialDenseMatrix to multiply with operator. + \param Out + Y -A Epetra_SerialDenseMatrix containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Apply(const Epetra_SerialDenseMatrix& X, Epetra_SerialDenseMatrix& Y) = 0; + + //! Returns the result of a Epetra_SerialDenseOperator inverse applied to an Epetra_SerialDenseMatrix X in Y. + /*! + \param In + X - A Epetra_SerialDenseMatrix to solve for. + \param Out + Y -A Epetra_SerialDenseMatrix containing result. + + \return Integer error code, set to 0 if successful. + + */ + virtual int ApplyInverse(const Epetra_SerialDenseMatrix & X, Epetra_SerialDenseMatrix & Y) = 0; + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f]. + + \warning This method must not be called unless HasNormInf() returns true. + */ + virtual double NormInf() const = 0; + //@} + + //! @name Atribute access functions + //@{ + + //! Returns a character string describing the operator + virtual const char * Label() const = 0; + + //! Returns the current UseTranspose setting. + virtual bool UseTranspose() const = 0; + + //! Returns true if the \e this object can provide an approximate Inf-norm, false otherwise. + virtual bool HasNormInf() const = 0; + + //! Returns the row dimension of operator + virtual int RowDim() const = 0; + + //! Returns the column dimension of operator + virtual int ColDim() const = 0; + //@} + +}; + +#endif /* _EPETRA_OPERATOR_H_ */ diff --git a/fastlib/trilinos/include/Epetra_SerialDenseSVD.h b/fastlib/trilinos/include/Epetra_SerialDenseSVD.h new file mode 100644 index 0000000000..0e84e64e4d --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialDenseSVD.h @@ -0,0 +1,507 @@ + +/* Copyright (2001) Sandia Corportation. Under the terms of Contract + * DE-AC04-94AL85000, there is a non-exclusive license for use of this + * work by or on behalf of the U.S. Government. Export of this program + * may require a license from the United States Government. */ + + +/* NOTICE: The United States Government is granted for itself and others + * acting on its behalf a paid-up, nonexclusive, irrevocable worldwide + * license in ths data to reproduce, prepare derivative works, and + * perform publicly and display publicly. Beginning five (5) years from + * July 25, 2001, the United States Government is granted for itself and + * others acting on its behalf a paid-up, nonexclusive, irrevocable + * worldwide license in this data to reproduce, prepare derivative works, + * distribute copies to the public, perform publicly and display + * publicly, and to permit others to do so. + * + * NEITHER THE UNITED STATES GOVERNMENT, NOR THE UNITED STATES DEPARTMENT + * OF ENERGY, NOR SANDIA CORPORATION, NOR ANY OF THEIR EMPLOYEES, MAKES + * ANY WARRANTY, EXPRESS OR IMPLIED, OR ASSUMES ANY LEGAL LIABILITY OR + * RESPONSIBILITY FOR THE ACCURACY, COMPLETENESS, OR USEFULNESS OF ANY + * INFORMATION, APPARATUS, PRODUCT, OR PROCESS DISCLOSED, OR REPRESENTS + * THAT ITS USE WOULD NOT INFRINGE PRIVATELY OWNED RIGHTS. */ + +#ifndef _EPETRA_SERIALDENSESVD_H_ +#define _EPETRA_SERIALDENSESVD_H_ + +#include "Epetra_SerialDenseOperator.h" +#include "Epetra_SerialDenseMatrix.h" +#include "Epetra_Object.h" +#include "Epetra_CompObject.h" +#include "Epetra_BLAS.h" +#include "Epetra_LAPACK.h" + + +//! Epetra_SerialDenseSVD: A class for SVDing dense linear problems. + +/*! The Epetra_SerialDenseSVD class enables the definition, in terms of Epetra_SerialDenseMatrix + and Epetra_SerialDenseVector objects, of a dense linear problem, followed by the solution of that problem via the + most sophisticated techniques available in LAPACK. + +The Epetra_SerialDenseSVD class is intended to provide full-featured support for solving linear +problems for general dense rectangular (or square) matrices. It is written on top of BLAS and LAPACK and thus has excellent +performance and numerical capabilities. Using this class, one can either perform simple factorizations and solves or +apply all the tricks available in LAPACK to get the best possible solution for very ill-conditioned problems. + +Epetra_SerialDenseSVD vs. Epetra_LAPACK + +The Epetra_LAPACK class provides access to most of the same functionality as Epetra_SerialDenseSolver. +The primary difference is that Epetra_LAPACK is a "thin" layer on top of LAPACK and Epetra_SerialDenseSolver +attempts to provide easy access to the more sophisticated aspects of solving dense linear and eigensystems. +
      +
    • When you should use Epetra_LAPACK: If you are simply looking for a convenient wrapper around the Fortran LAPACK + routines and you have a well-conditioned problem, you should probably use Epetra_LAPACK directly. +
    • When you should use Epetra_SerialDenseSolver: If you want to (or potentially want to) solve ill-conditioned + problems or want to work with a more object-oriented interface, you should probably use Epetra_SerialDenseSolver. + +
    + +Constructing Epetra_SerialDenseSVD Objects + +There is a single Epetra_SerialDenseSVD constructor. However, the matrix, right hand side and solution +vectors must be set prior to executing most methods in this class. + +Setting vectors used for linear solves + +The matrix A, the left hand side X and the right hand side B (when solving AX = B, for X), can be set by appropriate set +methods. Each of these three objects must be an Epetra_SerialDenseMatrix or and Epetra_SerialDenseVector object. The +set methods are as follows: +
      +
    • SetMatrix() - Sets the matrix. +
    • SetVectors() - Sets the left and right hand side vector(s). +
    + +Vector and Utility Functions + +Once a Epetra_SerialDenseSVD is constructed, several mathematical functions can be applied to +the object. Specifically: +
      +
    • Factorizations. +
    • Solves. +
    • Condition estimates. +
    • Norms. +
    + +Counting floating point operations +The Epetra_SerialDenseSVD class has Epetra_CompObject as a base class. Thus, floating point operations +are counted and accumulated in the Epetra_Flop object (if any) that was set using the SetFlopCounter() +method in the Epetra_CompObject base class. + +Examples using Epetra_SerialDenseSVD can be found in the Epetra test directories. + +*/ + +//========================================================================= +class Epetra_SerialDenseSVD : public virtual Epetra_SerialDenseOperator, public Epetra_CompObject, public virtual Epetra_Object, public Epetra_BLAS, public Epetra_LAPACK{ + public: + + //! @name Constructor/Destructor Methods + //@{ + //! Default constructor; matrix should be set using SetMatrix(), LHS and RHS set with SetVectors(). + Epetra_SerialDenseSVD(); + + //! Epetra_SerialDenseSVD destructor. + virtual ~Epetra_SerialDenseSVD(); + //@} + + //! @name Set Methods + //@{ + + //! Sets the pointers for coefficient matrix + int SetMatrix(Epetra_SerialDenseMatrix & A); + + //! Sets the pointers for left and right hand side vector(s). + /*! Row dimension of X must match column dimension of matrix A, row dimension of B + must match row dimension of A. X and B must have the same dimensions. + */ + int SetVectors(Epetra_SerialDenseMatrix & X, Epetra_SerialDenseMatrix & B); + //@} + + //! @name Strategy modifying Methods + //@{ + + //! Causes equilibration to be called just before the matrix factorization as part of the call to Factor. + /*! This function must be called before the factorization is performed. + */ +// void FactorWithEquilibration(bool Flag) {Equilibrate_ = Flag; return;}; + + //! If Flag is true, causes all subsequent function calls to work with the transpose of \e this matrix, otherwise not. + void SolveWithTranspose(bool Flag) {Transpose_ = Flag; if (Flag) TRANS_ = 'T'; else TRANS_ = 'N'; return;}; + + //! Causes all solves to compute solution to best ability using iterative refinement. +// void SolveToRefinedSolution(bool Flag) {RefineSolution_ = Flag; return;}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Causes all solves to estimate the forward and backward solution error. + /* Error estimates will be in the arrays FERR and BERR, resp, after the solve step is complete. + These arrays are accessible via the FERR() and BERR() access functions. + */ +// void EstimateSolutionErrors(bool Flag) {EstimateSolutionErrors_ = Flag; return;}; + //@} + + //! @name Factor/Solve/Invert Methods + //@{ + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Computes the SVD factorization of the matrix using the LAPACK routine \e DGESVD. + /* + \return Integer error code, set to 0 if successful. + */ +// virtual int Factor(void); + virtual int Factor(void); + + //! Computes the solution X to AX = B for the \e this matrix and the B provided to SetVectors().. + /*! Inverse of Matrix must be formed + \return Integer error code, set to 0 if successful. + */ + virtual int Solve(void); + + //! Inverts the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + virtual int Invert( double rthresh = 0.0, double athresh = 0.0 ); + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Computes the scaling vector S(i) = 1/sqrt(A(i,i) of the \e this matrix. + /* + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ +// virtual int ComputeEquilibrateScaling(void); + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Equilibrates the \e this matrix. + /* + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ +// virtual int EquilibrateMatrix(void); + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Equilibrates the current RHS. + /* + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ +// int EquilibrateRHS(void); + + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Apply Iterative Refinement. + /* + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ +// virtual int ApplyRefinement(void); + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Unscales the solution vectors if equilibration was used to solve the system. + /* + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ +// int UnequilibrateLHS(void); + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns the reciprocal of the 1-norm condition number of the \e this matrix. + /* + \param Value Out + On return contains the reciprocal of the 1-norm condition number of the \e this matrix. + + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ +// virtual int ReciprocalConditionEstimate(double & Value); + //@} + + //! @name Query methods + //@{ + + //! Returns true if transpose of \e this matrix has and will be used. + bool Transpose() {return(Transpose_);}; + + //! Returns true if matrix is factored (factor available via AF() and LDAF()). + bool Factored() {return(Factored_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns true if factor is equilibrated (factor available via AF() and LDAF()). +// bool A_Equilibrated() {return(A_Equilibrated_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns true if RHS is equilibrated (RHS available via B() and LDB()). +// bool B_Equilibrated() {return(B_Equilibrated_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns true if the LAPACK general rules for equilibration suggest you should equilibrate the system. +// virtual bool ShouldEquilibrate() {ComputeEquilibrateScaling(); return(ShouldEquilibrate_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns true if forward and backward error estimated have been computed (available via FERR() and BERR()). +// bool SolutionErrorsEstimated() {return(SolutionErrorsEstimated_);}; + + //! Returns true if matrix inverse has been computed (inverse available via AF() and LDAF()). + bool Inverted() {return(Inverted_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns true if the condition number of the \e this matrix has been computed (value available via ReciprocalConditionEstimate()). +// bool ReciprocalConditionEstimated() {return(ReciprocalConditionEstimated_);}; + + //! Returns true if the current set of vectors has been solved. + bool Solved() {return(Solved_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns true if the current set of vectors has been refined. +// bool SolutionRefined() {return(SolutionRefined_);}; + //@} + + //! @name Data Accessor methods + //@{ + + //! Returns pointer to current matrix. + Epetra_SerialDenseMatrix * Matrix() const {return(Matrix_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns pointer to factored matrix (assuming factorization has been performed). +// Epetra_SerialDenseMatrix * FactoredMatrix() const {return(Factor_);}; + + //! Returns pointer to inverted matrix (assuming inverse has been performed). + Epetra_SerialDenseMatrix * InvertedMatrix() const {return(Inverse_);}; + + //! Returns pointer to current LHS. + Epetra_SerialDenseMatrix * LHS() const {return(LHS_);}; + + //! Returns pointer to current RHS. + Epetra_SerialDenseMatrix * RHS() const {return(RHS_);}; + + //! Returns row dimension of system. + int M() const {return(M_);}; + + //! Returns column dimension of system. + int N() const {return(N_);}; + + //! Returns pointer to the \e this matrix. + double * A() const {return(A_);}; + + //! Returns the leading dimension of the \e this matrix. + int LDA() const {return(LDA_);}; + + //! Returns pointer to current RHS. + double * B() const {return(B_);}; + + //! Returns the leading dimension of the RHS. + int LDB() const {return(LDB_);}; + + //! Returns the number of current right hand sides and solution vectors. + int NRHS() const {return(NRHS_);}; + + //! Returns pointer to current solution. + double * X() const {return(X_);}; + + //! Returns the leading dimension of the solution. + int LDX() const {return(LDX_);}; + + double * S() const {return(S_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns pointer to the factored matrix (may be the same as A() if factorization done in place). +// double * AF() const {return(AF_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns the leading dimension of the factored matrix. +// int LDAF() const {return(LDAF_);}; + + //! Returns pointer to the inverted matrix (may be the same as A() if factorization done in place). + double * AI() const {return(AI_);}; + + //! Returns the leading dimension of the inverted matrix. + int LDAI() const {return(LDAI_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns pointer to pivot vector (if factorization has been computed), zero otherwise. +// int * IPIV() const {return(IPIV_);}; + + //! Returns the 1-Norm of the \e this matrix (returns -1 if not yet computed). + double ANORM() const {return(ANORM_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns the reciprocal of the condition number of the \e this matrix (returns -1 if not yet computed). +// double RCOND() const {return(RCOND_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Ratio of smallest to largest row scale factors for the \e this matrix (returns -1 if not yet computed). + /* If ROWCND() is >= 0.1 and AMAX() is not close to overflow or underflow, then equilibration is not needed. + */ +// double ROWCND() const {return(ROWCND_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Ratio of smallest to largest column scale factors for the \e this matrix (returns -1 if not yet computed). + /* If COLCND() is >= 0.1 then equilibration is not needed. + */ +// double COLCND() const {return(COLCND_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns the absolute value of the largest entry of the \e this matrix (returns -1 if not yet computed). +// double AMAX() const {return(AMAX_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns a pointer to the forward error estimates computed by LAPACK. +// double * FERR() const {return(FERR_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns a pointer to the backward error estimates computed by LAPACK. +// double * BERR() const {return(BERR_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns a pointer to the row scaling vector used for equilibration. +// double * R() const {return(R_);}; + + // NOTE: doxygen-style documentation needs to be re-enabled if this function is re-enabled + // Returns a pointer to the column scale vector used for equilibration. +// double * C() const {return(C_);}; + //@} + + //! @name I/O methods + //@{ + //! Print service methods; defines behavior of ostream << operator. + virtual void Print(ostream& os) const; + //@} + + //! @name Additional methods for support of Epetra_SerialDenseOperator interface + //@{ + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param In + UseTranspose -If true, multiply by the transpose of operator, otherwise just use operator. + + \return Integer error code, set to 0 if successful. Set to -1 if this implementation does not support transpose. + */ + virtual int SetUseTranspose(bool UseTranspose) { UseTranspose_ = UseTranspose; return (0); } + + //! Returns the result of a Epetra_SerialDenseOperator applied to a Epetra_SerialDenseMatrix X in Y. + /*! + \param In + X - A Epetra_SerialDenseMatrix to multiply with operator. + \param Out + Y -A Epetra_SerialDenseMatrix containing result. + + \return Integer error code, set to 0 if successful. + */ + virtual int Apply(const Epetra_SerialDenseMatrix& X, Epetra_SerialDenseMatrix& Y) + { return Y.Multiply( UseTranspose_, false, 1.0, *Matrix(), X, 0.0 ); } + + //! Returns the result of a Epetra_SerialDenseOperator inverse applied to an Epetra_SerialDenseMatrix X in Y. + /*! + \param In + X - A Epetra_SerialDenseMatrix to solve for. + \param Out + Y -A Epetra_SerialDenseMatrix containing result. + + \return Integer error code, set to 0 if successful. + + */ + virtual int ApplyInverse(const Epetra_SerialDenseMatrix & X, Epetra_SerialDenseMatrix & Y) + { SetVectors(const_cast(X),Y); + SolveWithTranspose(UseTranspose_); + return Solve(); } + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f]. + + \warning This method must not be called unless HasNormInf() returns true. + */ + virtual double NormInf() const { return Matrix()->NormInf(); } + + //! Returns a character string describing the operator + virtual const char * Label() const { return Epetra_Object::Label(); } + + //! Returns the current UseTranspose setting. + virtual bool UseTranspose() const { return UseTranspose_; } + + //! Returns true if the \e this object can provide an approximate Inf-norm, false otherwise. + virtual bool HasNormInf() const { return true; } + + //! Returns the row dimension of operator + virtual int RowDim() const { return M(); } + + //! Returns the column dimension of operator + virtual int ColDim() const { return N(); } + + //@} + + void AllocateWORK() {if (WORK_==0) {LWORK_ = 4*N_; WORK_ = new double[LWORK_];} return;}; + void AllocateIWORK() {if (IWORK_==0) IWORK_ = new int[N_]; return;}; + void InitPointers(); + void DeleteArrays(); + void ResetMatrix(); + void ResetVectors(); + + +// bool Equilibrate_; +// bool ShouldEquilibrate_; +// bool A_Equilibrated_; +// bool B_Equilibrated_; + bool Transpose_; + bool Factored_; +// bool EstimateSolutionErrors_; +// bool SolutionErrorsEstimated_; + bool Solved_; + bool Inverted_; +// bool ReciprocalConditionEstimated_; +// bool RefineSolution_; +// bool SolutionRefined_; + + char TRANS_; + + int M_; + int N_; + int Min_MN_; + int NRHS_; + int LDA_; +// int LDAF_; + int LDAI_; + int LDB_; + int LDX_; + int INFO_; + int LWORK_; + +// int * IPIV_; + int * IWORK_; + + double ANORM_; +// double RCOND_; +// double ROWCND_; +// double COLCND_; +// double AMAX_; + + Epetra_SerialDenseMatrix * Matrix_; + Epetra_SerialDenseMatrix * LHS_; + Epetra_SerialDenseMatrix * RHS_; +// Epetra_SerialDenseMatrix * Factor_; + Epetra_SerialDenseMatrix * Inverse_; + + double * A_; +// double * FERR_; +// double * BERR_; +// double * AF_; + double * AI_; + double * WORK_; +// double * R_; +// double * C_; + double * U_; + double * S_; + double * Vt_; + + double * B_; + double * X_; + + bool UseTranspose_; + + private: + // Epetra_SerialDenseSolver copy constructor (put here because we don't want user access) + + Epetra_SerialDenseSVD(const Epetra_SerialDenseSVD& Source); + Epetra_SerialDenseSVD & operator=(const Epetra_SerialDenseSVD& Source); +}; + +#endif /* _EPETRA_SERIALDENSESVD_H_ */ diff --git a/fastlib/trilinos/include/Epetra_SerialDenseSolver.h b/fastlib/trilinos/include/Epetra_SerialDenseSolver.h new file mode 100644 index 0000000000..c878bf0b28 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialDenseSolver.h @@ -0,0 +1,422 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALDENSESOLVER_H +#define EPETRA_SERIALDENSESOLVER_H +class Epetra_SerialDenseMatrix; +#include "Epetra_Object.h" +#include "Epetra_CompObject.h" +#include "Epetra_BLAS.h" +#include "Epetra_LAPACK.h" + + +//! Epetra_SerialDenseSolver: A class for solving dense linear problems. + +/*! The Epetra_SerialDenseSolver class enables the definition, in terms of Epetra_SerialDenseMatrix + and Epetra_SerialDenseVector objects, of a dense linear problem, followed by the solution of that problem via the + most sophisticated techniques available in LAPACK. + +The Epetra_SerialDenseSolver class is intended to provide full-featured support for solving linear +problems for general dense rectangular (or square) matrices. It is written on top of BLAS and LAPACK and thus has excellent +performance and numerical capabilities. Using this class, one can either perform simple factorizations and solves or +apply all the tricks available in LAPACK to get the best possible solution for very ill-conditioned problems. + +Epetra_SerialDenseSolver vs. Epetra_LAPACK + +The Epetra_LAPACK class provides access to most of the same functionality as Epetra_SerialDenseSolver. +The primary difference is that Epetra_LAPACK is a "thin" layer on top of LAPACK and Epetra_SerialDenseSolver +attempts to provide easy access to the more sophisticated aspects of solving dense linear and eigensystems. +
      +
    • When you should use Epetra_LAPACK: If you are simply looking for a convenient wrapper around the Fortran LAPACK + routines and you have a well-conditioned problem, you should probably use Epetra_LAPACK directly. +
    • When you should use Epetra_SerialDenseSolver: If you want to (or potentially want to) solve ill-conditioned + problems or want to work with a more object-oriented interface, you should probably use Epetra_SerialDenseSolver. + +
    + +Constructing Epetra_SerialDenseSolver Objects + +There is a single Epetra_SerialDenseSolver constructor. However, the matrix, right hand side and solution +vectors must be set prior to executing most methods in this class. + +Setting vectors used for linear solves + +The matrix A, the left hand side X and the right hand side B (when solving AX = B, for X), can be set by appropriate set +methods. Each of these three objects must be an Epetra_SerialDenseMatrix or and Epetra_SerialDenseVector object. The +set methods are as follows: +
      +
    • SetMatrix() - Sets the matrix. +
    • SetVectors() - Sets the left and right hand side vector(s). +
    + +Vector and Utility Functions + +Once a Epetra_SerialDenseSolver is constructed, several mathematical functions can be applied to +the object. Specifically: +
      +
    • Factorizations. +
    • Solves. +
    • Condition estimates. +
    • Equilibration. +
    • Norms. +
    + +Counting floating point operations +The Epetra_SerialDenseSolver class has Epetra_CompObject as a base class. Thus, floating point operations +are counted and accumulated in the Epetra_Flop object (if any) that was set using the SetFlopCounter() +method in the Epetra_CompObject base class. + +Strategies for Solving Linear Systems +In many cases, linear systems can be accurately solved by simply computing the LU factorization +of the matrix and then performing a forward back solve with a given set of right hand side vectors. However, +in some instances, the factorization may be very poorly conditioned and this simple approach may not work. In +these situations, equilibration and iterative refinement may improve the accuracy, or prevent a breakdown in +the factorization. + +Epetra_SerialDenseSolver will use equilibration with the factorization if, once the object +is constructed and \e before it is factored, you call the function FactorWithEquilibration(true) to force +equilibration to be used. If you are uncertain if equilibration should be used, you may call the function +ShouldEquilibrate() which will return true if equilibration could possibly help. ShouldEquilibrate() uses +guidelines specified in the LAPACK User Guide, namely if SCOND < 0.1 and AMAX < Underflow or AMAX > Overflow, to +determine if equilibration \e might be useful. + +Epetra_SerialDenseSolver will use iterative refinement after a forward/back solve if you call +SolveToRefinedSolution(true). It will also compute forward and backward error estimates if you call +EstimateSolutionErrors(true). Access to the forward (back) error estimates is available via FERR() (BERR()). + +Examples using Epetra_SerialDenseSolver can be found in the Epetra test directories. + +*/ + +//========================================================================= +class Epetra_SerialDenseSolver : public Epetra_CompObject, public Epetra_BLAS, + public Epetra_LAPACK, public Epetra_Object { + public: + + //! @name Constructor/Destructor Methods + //@{ + //! Default constructor; matrix should be set using SetMatrix(), LHS and RHS set with SetVectors(). + Epetra_SerialDenseSolver(); + + + //! Epetra_SerialDenseSolver destructor. + virtual ~Epetra_SerialDenseSolver(); + //@} + + //! @name Set Methods + //@{ + + //! Sets the pointers for coefficient matrix + int SetMatrix(Epetra_SerialDenseMatrix & A); + + //! Sets the pointers for left and right hand side vector(s). + /*! Row dimension of X must match column dimension of matrix A, row dimension of B + must match row dimension of A. X and B must have the same dimensions. + */ + int SetVectors(Epetra_SerialDenseMatrix & X, Epetra_SerialDenseMatrix & B); + //@} + + //! @name Strategy modifying Methods + //@{ + + //! Causes equilibration to be called just before the matrix factorization as part of the call to Factor. + /*! This function must be called before the factorization is performed. + */ + void FactorWithEquilibration(bool Flag) {Equilibrate_ = Flag; return;}; + + //! If Flag is true, causes all subsequent function calls to work with the transpose of \e this matrix, otherwise not. + void SolveWithTranspose(bool Flag) {Transpose_ = Flag; if (Flag) TRANS_ = 'T'; else TRANS_ = 'N'; return;}; + + //! Causes all solves to compute solution to best ability using iterative refinement. + void SolveToRefinedSolution(bool Flag) {RefineSolution_ = Flag; return;}; + + //! Causes all solves to estimate the forward and backward solution error. + /*! Error estimates will be in the arrays FERR and BERR, resp, after the solve step is complete. + These arrays are accessible via the FERR() and BERR() access functions. + */ + void EstimateSolutionErrors(bool Flag) ; + //@} + + //! @name Factor/Solve/Invert Methods + //@{ + + //! Computes the in-place LU factorization of the matrix using the LAPACK routine \e DGETRF. + /*! + \return Integer error code, set to 0 if successful. + */ + virtual int Factor(void); + + //! Computes the solution X to AX = B for the \e this matrix and the B provided to SetVectors().. + /*! + \return Integer error code, set to 0 if successful. + */ + virtual int Solve(void); + + //! Inverts the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + virtual int Invert(void); + + //! Computes the scaling vector S(i) = 1/sqrt(A(i,i)) of the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + virtual int ComputeEquilibrateScaling(void); + + //! Equilibrates the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + virtual int EquilibrateMatrix(void); + + //! Equilibrates the current RHS. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int EquilibrateRHS(void); + + + //! Apply Iterative Refinement. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + virtual int ApplyRefinement(void); + + //! Unscales the solution vectors if equilibration was used to solve the system. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int UnequilibrateLHS(void); + + //! Returns the reciprocal of the 1-norm condition number of the \e this matrix. + /*! + \param Value Out + On return contains the reciprocal of the 1-norm condition number of the \e this matrix. + + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + virtual int ReciprocalConditionEstimate(double & Value); + //@} + + //! @name Query methods + //@{ + + //! Returns true if transpose of \e this matrix has and will be used. + bool Transpose() {return(Transpose_);}; + + //! Returns true if matrix is factored (factor available via AF() and LDAF()). + bool Factored() {return(Factored_);}; + + //! Returns true if factor is equilibrated (factor available via AF() and LDAF()). + bool A_Equilibrated() {return(A_Equilibrated_);}; + + //! Returns true if RHS is equilibrated (RHS available via B() and LDB()). + bool B_Equilibrated() {return(B_Equilibrated_);}; + + //! Returns true if the LAPACK general rules for equilibration suggest you should equilibrate the system. + virtual bool ShouldEquilibrate() {ComputeEquilibrateScaling(); return(ShouldEquilibrate_);}; + + //! Returns true if forward and backward error estimated have been computed (available via FERR() and BERR()). + bool SolutionErrorsEstimated() {return(SolutionErrorsEstimated_);}; + + //! Returns true if matrix inverse has been computed (inverse available via AF() and LDAF()). + bool Inverted() {return(Inverted_);}; + + //! Returns true if the condition number of the \e this matrix has been computed (value available via ReciprocalConditionEstimate()). + bool ReciprocalConditionEstimated() {return(ReciprocalConditionEstimated_);}; + + //! Returns true if the current set of vectors has been solved. + bool Solved() {return(Solved_);}; + + //! Returns true if the current set of vectors has been refined. + bool SolutionRefined() {return(SolutionRefined_);}; + //@} + + //! @name Data Accessor methods + //@{ + + //! Returns pointer to current matrix. + Epetra_SerialDenseMatrix * Matrix() const {return(Matrix_);}; + + //! Returns pointer to factored matrix (assuming factorization has been performed). + Epetra_SerialDenseMatrix * FactoredMatrix() const {return(Factor_);}; + + //! Returns pointer to current LHS. + Epetra_SerialDenseMatrix * LHS() const {return(LHS_);}; + + //! Returns pointer to current RHS. + Epetra_SerialDenseMatrix * RHS() const {return(RHS_);}; + + //! Returns row dimension of system. + int M() const {return(M_);}; + + //! Returns column dimension of system. + int N() const {return(N_);}; + + //! Returns pointer to the \e this matrix. + double * A() const {return(A_);}; + + //! Returns the leading dimension of the \e this matrix. + int LDA() const {return(LDA_);}; + + //! Returns pointer to current RHS. + double * B() const {return(B_);}; + + //! Returns the leading dimension of the RHS. + int LDB() const {return(LDB_);}; + + //! Returns the number of current right hand sides and solution vectors. + int NRHS() const {return(NRHS_);}; + + //! Returns pointer to current solution. + double * X() const {return(X_);}; + + //! Returns the leading dimension of the solution. + int LDX() const {return(LDX_);}; + + //! Returns pointer to the factored matrix (may be the same as A() if factorization done in place). + double * AF() const {return(AF_);}; + + //! Returns the leading dimension of the factored matrix. + int LDAF() const {return(LDAF_);}; + + //! Returns pointer to pivot vector (if factorization has been computed), zero otherwise. + int * IPIV() const {return(IPIV_);}; + + //! Returns the 1-Norm of the \e this matrix (returns -1 if not yet computed). + double ANORM() const {return(ANORM_);}; + + //! Returns the reciprocal of the condition number of the \e this matrix (returns -1 if not yet computed). + double RCOND() const {return(RCOND_);}; + + //! Ratio of smallest to largest row scale factors for the \e this matrix (returns -1 if not yet computed). + /*! If ROWCND() is >= 0.1 and AMAX() is not close to overflow or underflow, then equilibration is not needed. + */ + double ROWCND() const {return(ROWCND_);}; + + //! Ratio of smallest to largest column scale factors for the \e this matrix (returns -1 if not yet computed). + /*! If COLCND() is >= 0.1 then equilibration is not needed. + */ + double COLCND() const {return(COLCND_);}; + + //! Returns the absolute value of the largest entry of the \e this matrix (returns -1 if not yet computed). + double AMAX() const {return(AMAX_);}; + + //! Returns a pointer to the forward error estimates computed by LAPACK. + double * FERR() const {return(FERR_);}; + + //! Returns a pointer to the backward error estimates computed by LAPACK. + double * BERR() const {return(BERR_);}; + + //! Returns a pointer to the row scaling vector used for equilibration. + double * R() const {return(R_);}; + + //! Returns a pointer to the column scale vector used for equilibration. + double * C() const {return(C_);}; + //@} + + //! @name I/O methods + //@{ + //! Print service methods; defines behavior of ostream << operator. + virtual void Print(ostream& os) const; + //@} + protected: + + void AllocateWORK() {if (WORK_==0) {LWORK_ = 4*N_; WORK_ = new double[LWORK_];} return;}; + void AllocateIWORK() {if (IWORK_==0) IWORK_ = new int[N_]; return;}; + void InitPointers(); + void DeleteArrays(); + void ResetMatrix(); + void ResetVectors(); + + + bool Equilibrate_; + bool ShouldEquilibrate_; + bool A_Equilibrated_; + bool B_Equilibrated_; + bool Transpose_; + bool Factored_; + bool EstimateSolutionErrors_; + bool SolutionErrorsEstimated_; + bool Solved_; + bool Inverted_; + bool ReciprocalConditionEstimated_; + bool RefineSolution_; + bool SolutionRefined_; + + char TRANS_; + + int M_; + int N_; + int Min_MN_; + int NRHS_; + int LDA_; + int LDAF_; + int LDB_; + int LDX_; + int INFO_; + int LWORK_; + + int * IPIV_; + int * IWORK_; + + double ANORM_; + double RCOND_; + double ROWCND_; + double COLCND_; + double AMAX_; + + Epetra_SerialDenseMatrix * Matrix_; + Epetra_SerialDenseMatrix * LHS_; + Epetra_SerialDenseMatrix * RHS_; + Epetra_SerialDenseMatrix * Factor_; + + double * A_; + double * FERR_; + double * BERR_; + double * AF_; + double * WORK_; + double * R_; + double * C_; + + double * B_; + double * X_; + + + private: + // Epetra_SerialDenseSolver copy constructor (put here because we don't want user access) + + Epetra_SerialDenseSolver(const Epetra_SerialDenseSolver& Source); + Epetra_SerialDenseSolver & operator=(const Epetra_SerialDenseSolver& Source); +}; + +#endif /* EPETRA_SERIALDENSESOLVER_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialDenseVector.h b/fastlib/trilinos/include/Epetra_SerialDenseVector.h new file mode 100644 index 0000000000..e3c1f9441e --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialDenseVector.h @@ -0,0 +1,311 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALDENSEVECTOR_H +#define EPETRA_SERIALDENSEVECTOR_H + +#include "Epetra_Object.h" +#include "Epetra_SerialDenseMatrix.h" + +//! Epetra_SerialDenseVector: A class for constructing and using dense vectors. + +/*! The Epetra_SerialDenseVector class enables the construction and use of real-valued, + double-precision dense vectors. It is built on the BLAS and LAPACK and derives from the Epetra_SerialDenseMatrix class. + +The Epetra_SerialDenseVector class is intended to provide convenient vector notation but derives all signficant +functionality from Epetra_SerialDenseMatrix. + +Constructing Epetra_SerialDenseVector Objects + +There are four Epetra_SerialDenseVector constructors. The first constructs a zero-length object which should be made +to appropriate length using the Size() or Resize() functions and then filled with the [] or () operators. +The second constructs an object sized to the dimension specified, which should be filled with the [] or () operators. +The third is a constructor that accepts user +data as a 1D array, and the fourth is a copy constructor. The third constructor has +two data access modes (specified by the Epetra_DataAccess argument): +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the object. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +Extracting Data from Epetra_SerialDenseVector Objects + +Once a Epetra_SerialDenseVector is constructed, it is possible to view the data via access functions. + +\warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective. + + +The final useful function is Flops(). Each Epetra_SerialDenseVector object keep track of the number +of \e serial floating point operations performed using the specified object as the \e this argument +to the function. The Flops() function returns this number as a double precision number. Using this +information, in conjunction with the Epetra_Time class, one can get accurate parallel performance +numbers. + + +*/ + + +//========================================================================= +class Epetra_SerialDenseVector : public Epetra_SerialDenseMatrix{ + + public: + + //! @name Constructors/destructors + //@{ + //! Default constructor; defines a zero size object. + /*! + Epetra_SerialDenseVector objects defined by the default constructor should be sized with the + Size() or Resize functions. + Values should be defined by using the [] or () operators. + */ + Epetra_SerialDenseVector(); + + //! Sized constructor; defines a variable-sized object + /*! + \param In + Length - Length of vector. + + Epetra_SerialDenseVector objects defined by the sized constructor are already sized to the + dimension given as a parameter. All values are initialized to 0. Calling this constructor + is equivalent to using the default constructor, and then calling the Size function on it. + Values should be defined by using the [] or () operators. + */ + Epetra_SerialDenseVector(int Length); + + //! Set object values from one-dimensional array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Values - Pointer to an array of double precision numbers containing the values. + \param In + Length - Length of vector. + + See Detailed Description section for further discussion. + */ + Epetra_SerialDenseVector(Epetra_DataAccess CV, double* Values, int Length); + + //! Epetra_SerialDenseVector copy constructor. + + Epetra_SerialDenseVector(const Epetra_SerialDenseVector& Source); + + + //! Epetra_SerialDenseVector destructor. + virtual ~Epetra_SerialDenseVector (); + //@} + + //! @name Post-construction modification routines + //@{ + + //! Set length of a Epetra_SerialDenseVector object; init values to zero. + /*! + \param In + Length - Length of vector object. + + Allows user to define the dimension of a Epetra_SerialDenseVector. This function can + be called at any point after construction. Any values that were previously in this object are + destroyed and the resized vector starts off with all zero values. + + \return Integer error code, set to 0 if successful. + */ + int Size(int Length) {return(Epetra_SerialDenseMatrix::Shape(Length, 1));}; + + //! Resize a Epetra_SerialDenseVector object. + /*! + \param In + Length - Length of vector object. + + Allows user to define the dimension of a Epetra_SerialDenseVector. This function can + be called at any point after construction. Any values that were previously in this object are + copied into the new size. If the new shape is smaller than the original, the first Length values + are copied to the new vector. + + \return Integer error code, set to 0 if successful. + */ + int Resize(int Length) {return(Epetra_SerialDenseMatrix::Reshape(Length, 1));}; + + //@} + + //! @name Element access methods + //@{ + //! Value copy from one vector to another. + /*! + The operator= allows one to copy the values from one existing SerialDenseVector to another, as + long as there is enough room in the target to hold the source. + + \return Values of the left hand side vector are modified by the values of the right hand side vector. + */ + Epetra_SerialDenseVector& operator = (const Epetra_SerialDenseVector& Source); + + //let the compiler know we intend to overload the base-class function + //operator() rather than hide it. + using Epetra_SerialDenseMatrix::operator(); + + //! Element access function. + /*! + Returns the specified element of the vector. Bounds checking is enforced. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + double& operator () (int Index); + + //! Element access function. + /*! + Returns the specified element of the vector. Bounds checking is enforced. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const double& operator () (int Index) const; + + //! Element access function. + /*! + Returns the specified element of the vector. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + double& operator [] (int Index); + + //! Column access function. + /*! + Returns the specified element of the vector. + \return Specified element in vector. + + \warning No bounds checking is done unless Epetra is compiled with HAVE_EPETRA_ARRAY_BOUNDS_CHECK. + */ + const double& operator [] (int Index) const; + + //@} + + //! @name Mathematical methods + //@{ + //! Set vector values to random numbers. + /*! + SerialDenseVector uses the random number generator provided by Epetra_Util. + The vector values will be set to random values on the interval (-1.0, 1.0). + + \return Integer error code, set to 0 if successful. + */ + int Random(); + + //! Compute 1-norm of each vector in multi-vector. + /*! + \param x (In) Input vector x. + + \return Dot-product of the \e this vector and x. + */ + double Dot(const Epetra_SerialDenseVector & x) const; + + //! Compute 1-norm of each vector in multi-vector. + /*! + \return 1-norm of the vector. + */ + double Norm1() const; + + //! Compute 2-norm of each vector in multi-vector. + /*! + \param Out + \return 2-norm of the vector. + */ + double Norm2() const; + + //! Compute Inf-norm of each vector in multi-vector. + /*! + \return Infinity-norm of the vector. + */ + double NormInf() const; + + //@} + + //! @name Attribute access methods + //@{ + //! Returns length of vector. + int Length() const {return(M_);}; + + //! Returns pointer to the values in vector. + double* Values() const {return(A_);}; + + //! Returns the data access mode of the \e this vector. + Epetra_DataAccess CV() const {return(CV_);}; + + //@} + + //! @name I/O methods + //@{ + //! Print service methods; defines behavior of ostream << operator. + virtual void Print(ostream& os) const; + //@} +}; + +// inlined definitions of op() and op[] +//========================================================================= +inline double& Epetra_SerialDenseVector::operator() (int Index) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (Index >= M_ || Index < 0) + throw ReportError("Index = " +toString(Index) + " Out of Range 0 - " + toString(M_-1), -1); +#endif + return(A_[Index]); +} +//========================================================================= +inline const double& Epetra_SerialDenseVector::operator() (int Index) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (Index >= M_ || Index < 0) + throw ReportError("Index = " +toString(Index) + " Out of Range 0 - " + toString(M_-1), -1); +#endif + return(A_[Index]); +} +//========================================================================= +inline double& Epetra_SerialDenseVector::operator [] (int Index) { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (Index >= M_ || Index < 0) + throw ReportError("Index = " +toString(Index) + " Out of Range 0 - " + toString(M_-1), -1); +#endif + return(A_[Index]); +} +//========================================================================= +inline const double& Epetra_SerialDenseVector::operator [] (int Index) const { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + if (Index >= M_ || Index < 0) + throw ReportError("Index = " +toString(Index) + " Out of Range 0 - " + toString(M_-1), -1); +#endif + return(A_[Index]); +} +//========================================================================= + +#endif /* EPETRA_SERIALDENSEVECTOR_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialDistributor.h b/fastlib/trilinos/include/Epetra_SerialDistributor.h new file mode 100644 index 0000000000..a704705c53 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialDistributor.h @@ -0,0 +1,133 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALDISTRIBUTOR_H +#define EPETRA_SERIALDISTRIBUTOR_H + +#include "Epetra_Object.h" +#include "Epetra_Distributor.h" +class Epetra_SerialComm; + +//! Epetra_SerialDistributor: The Epetra Serial implementation of the Epetra_Distributor Gather/Scatter Setup Class. +/*! The Epetra_SerialDistributor class is an Serial implement of Epetra_Distributor that is essentially a trivial class + since a serial machine is a trivial parallel machine. + An Epetra_SerialDistributor object is actually produced by calling a method in the Epetra_SerialComm class. + +*/ + +class Epetra_SerialDistributor: public Epetra_Object, public virtual Epetra_Distributor { + + public: + + //! @name Constructor/Destructor + //@{ + + //! Constructor. + Epetra_SerialDistributor(const Epetra_SerialComm & Comm); + + //! Epetra_SerialDistributor Copy Constructor. + Epetra_SerialDistributor(const Epetra_SerialDistributor & Plan); + + //! Clone method + Epetra_Distributor * Clone(){return(dynamic_cast(new Epetra_SerialDistributor(*this)));}; + + //! Epetra_Comm Destructor. + virtual ~Epetra_SerialDistributor(); + //@} + + + int CreateFromSends( const int & NumExportIDs, + const int * ExportPIDs, + bool Deterministic, + int & NumRemoteIDs ); + + int CreateFromRecvs( const int & NumRemoteIDs, + const int * RemoteGIDs, + const int * RemotePIDs, + bool Deterministic, + int & NumExportIDs, + int *& ExportGIDs, + int *& ExportPIDs); + + + int Do (char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs); + int DoReverse(char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs); + + int DoPosts(char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs); + int DoWaits(); + + int DoReversePosts(char * export_objs, + int obj_size, + int & len_import_objs, + char *& import_objs); + int DoReverseWaits(); + + + int Do (char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs); + int DoReverse(char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs); + + int DoPosts(char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs); + + int DoReversePosts(char * export_objs, + int obj_size, + int *& sizes, + int & len_import_objs, + char *& import_objs); + + + virtual void Print(ostream & os) const; + + private: + int nrecvs_; + int nsends_; +}; +#endif /* EPETRA_SERIALDISTRIBUTOR_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialSpdDenseSolver.h b/fastlib/trilinos/include/Epetra_SerialSpdDenseSolver.h new file mode 100644 index 0000000000..911d58111a --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialSpdDenseSolver.h @@ -0,0 +1,265 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALSPDDENSESOLVER_H +#define EPETRA_SERIALSPDDENSESOLVER_H +#include "Epetra_SerialDenseSolver.h" +class Epetra_SerialSymDenseMatrix; + +//! Epetra_SerialSpdDenseSolver: A class for constructing and using symmetric positive definite dense matrices. + +/*! The Epetra_SerialSpdDenseSolver class enables the construction and use of real-valued, symmetric positive definite, + double-precision dense matrices. It is built on the Epetra_DenseMatrix class which in turn is built on the + BLAS and LAPACK via the Epetra_BLAS and + Epetra_LAPACK classes. + +The Epetra_SerialSpdDenseSolver class is intended to provide full-featured support for solving linear and eigen system +problems for symmetric positive definite matrices. It is written on top of BLAS and LAPACK and thus has excellent +performance and numerical capabilities. Using this class, one can either perform simple factorizations and solves or +apply all the tricks available in LAPACK to get the best possible solution for very ill-conditioned problems. + +Epetra_SerialSpdDenseSolver vs. Epetra_LAPACK + +The Epetra_LAPACK class provides access to most of the same functionality as Epetra_SerialSpdDenseSolver. +The primary difference is that Epetra_LAPACK is a "thin" layer on top of LAPACK and Epetra_SerialSpdDenseSolver +attempts to provide easy access to the more sophisticated aspects of solving dense linear and eigensystems. +
      +
    • When you should use Epetra_LAPACK: If you are simply looking for a convenient wrapper around the Fortran LAPACK + routines and you have a well-conditioned problem, you should probably use Epetra_LAPACK directly. +
    • When you should use Epetra_SerialSpdDenseSolver: If you want to (or potentially want to) solve ill-conditioned + problems or want to work with a more object-oriented interface, you should probably use Epetra_SerialSpdDenseSolver. + +
    + +Constructing Epetra_SerialSpdDenseSolver Objects + +There are three Epetra_DenseMatrix constructors. The first constructs a zero-sized object which should be made +to appropriate length using the Shape() or Reshape() functions and then filled with the [] or () operators. +The second is a constructor that accepts user +data as a 2D array, the third is a copy constructor. The second constructor has +two data access modes (specified by the Epetra_DataAccess argument): +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the object. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +Setting vectors used for linear solves + +Setting the X and B vectors (which are Epetra_DenseMatrix objects) used for solving linear systems +is done separately from the constructor. This allows +a single matrix factor to be used for multiple solves. Similar to the constructor, the vectors X and B can +be copied or viewed using the Epetra_DataAccess argument. + +Extracting Data from Epetra_SerialSpdDenseSolver Objects + +Once a Epetra_SerialSpdDenseSolver is constructed, it is possible to view the data via access functions. + +\warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective. + + +Vector and Utility Functions + +Once a Epetra_SerialSpdDenseSolver is constructed, several mathematical functions can be applied to +the object. Specifically: +
      +
    • Factorizations. +
    • Solves. +
    • Condition estimates. +
    • Equilibration. +
    • Norms. +
    + +The final useful function is Flops(). Each Epetra_SerialSpdDenseSolver object keep track of the number +of \e serial floating point operations performed using the specified object as the \e this argument +to the function. The Flops() function returns this number as a double precision number. Using this +information, in conjunction with the Epetra_Time class, one can get accurate parallel performance +numbers. + +Strategies for Solving Linear Systems +In many cases, linear systems can be accurately solved by simply computing the Cholesky factorization +of the matrix and then performing a forward back solve with a given set of right hand side vectors. However, +in some instances, the factorization may be very poorly conditioned and the simple approach may not work. In +these situations, equilibration and iterative refinement may improve the accuracy, or prevent a breakdown in +the factorization. + +Epetra_SerialSpdDenseSolver will use equilibration with the factorization if, once the object +is constructed and \e before it is factored, you call the function FactorWithEquilibration(true) to force +equilibration to be used. If you are uncertain if equilibration should be used, you may call the function +ShouldEquilibrate() which will return true if equilibration could possibly help. ShouldEquilibrate() uses +guidelines specified in the LAPACK User Guide, namely if SCOND < 0.1 and AMAX < Underflow or AMAX > Overflow, to +determine if equilibration \e might be useful. + +Epetra_SerialSpdDenseSolver will use iterative refinement after a forward/back solve if you call +SolveToRefinedSolution(true). It will also compute forward and backward error estimates if you call +EstimateSolutionErrors(true). Access to the forward (back) error estimates is available via FERR() (BERR()). + +Examples using Epetra_SerialSpdDenseSolver can be found in the Epetra test directories. + +*/ + +//========================================================================= +class Epetra_SerialSpdDenseSolver : public Epetra_SerialDenseSolver { + + public: + //! @name Constructor/Destructor Methods + //@{ + //! Default constructor; matrix should be set using SetMatrix(), LHS and RHS set with SetVectors(). + Epetra_SerialSpdDenseSolver(); + + + //! Epetra_SerialDenseSolver destructor. + virtual ~Epetra_SerialSpdDenseSolver(); + //@} + + //! @name Set Methods + //@{ + + //Let the compiler know we intend to overload the SetMatrix function, + //rather than hide it. + using Epetra_SerialDenseSolver::SetMatrix; + + //! Sets the pointers for coefficient matrix; special version for symmetric matrices + int SetMatrix(Epetra_SerialSymDenseMatrix & A); + //@} + + //! @name Factor/Solve/Invert Methods + //@{ + + //! Computes the in-place Cholesky factorization of the matrix using the LAPACK routine \e DPOTRF. + /*! + \return Integer error code, set to 0 if successful. + */ + int Factor(void); + + //! Computes the solution X to AX = B for the \e this matrix and the B provided to SetVectors().. + /*! + \return Integer error code, set to 0 if successful. + */ + int Solve(void); + + //! Inverts the \e this matrix. + /*! Note: This function works a little differently that DPOTRI in that it fills the entire + matrix with the inverse, independent of the UPLO specification. + + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int Invert(void); + + //! Computes the scaling vector S(i) = 1/sqrt(A(i,i) of the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int ComputeEquilibrateScaling(void); + + //! Equilibrates the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int EquilibrateMatrix(void); + + //! Equilibrates the current RHS. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int EquilibrateRHS(void); + + + //! Apply Iterative Refinement. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int ApplyRefinement(void); + + //! Unscales the solution vectors if equilibration was used to solve the system. + /*! + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int UnequilibrateLHS(void); + + //! Returns the reciprocal of the 1-norm condition number of the \e this matrix. + /*! + \param Value Out + On return contains the reciprocal of the 1-norm condition number of the \e this matrix. + + \return Integer error code, set to 0 if successful. Otherwise returns the LAPACK error code INFO. + */ + int ReciprocalConditionEstimate(double & Value); + //@} + + //! @name Query methods + //@{ + + + //! Returns true if the LAPACK general rules for equilibration suggest you should equilibrate the system. + bool ShouldEquilibrate() {ComputeEquilibrateScaling(); return(ShouldEquilibrate_);}; + //@} + + //! @name Data Accessor methods + //@{ + + //! Returns pointer to current matrix. + Epetra_SerialSymDenseMatrix * SymMatrix() const {return(SymMatrix_);}; + + //! Returns pointer to factored matrix (assuming factorization has been performed). + Epetra_SerialSymDenseMatrix * SymFactoredMatrix() const {return(SymFactor_);}; + + //! Ratio of smallest to largest equilibration scale factors for the \e this matrix (returns -1 if not yet computed). + /*! If SCOND() is >= 0.1 and AMAX() is not close to overflow or underflow, then equilibration is not needed. + */ + double SCOND() {return(SCOND_);}; + + //Let the compiler know we intend to overload the AMAX function, + //rather than hide it. + using Epetra_SerialDenseSolver::AMAX; + + //! Returns the absolute value of the largest entry of the \e this matrix (returns -1 if not yet computed). + double AMAX() {return(AMAX_);}; + //@} + + private: + + double SCOND_; + Epetra_SerialSymDenseMatrix * SymMatrix_; // Need pointer to symmetric matrix for Spd-specific methods + Epetra_SerialSymDenseMatrix * SymFactor_; // Need pointer to symmetric matrix for Spd-specific methods + + // Epetra_SerialSpdDenseSolver copy constructor (put here because we don't want user access) + + Epetra_SerialSpdDenseSolver(const Epetra_SerialSpdDenseSolver& Source); + Epetra_SerialSpdDenseSolver & operator=(const Epetra_SerialSpdDenseSolver& Source); +}; + +#endif /* EPETRA_SERIALSPDDENSESOLVER_H */ diff --git a/fastlib/trilinos/include/Epetra_SerialSymDenseMatrix.h b/fastlib/trilinos/include/Epetra_SerialSymDenseMatrix.h new file mode 100644 index 0000000000..ea940d8715 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SerialSymDenseMatrix.h @@ -0,0 +1,270 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SERIALSYMDENSEMATRIX_H +#define EPETRA_SERIALSYMDENSEMATRIX_H +#include "Epetra_SerialDenseMatrix.h" + + +//! Epetra_SerialSymDenseMatrix: A class for constructing and using symmetric positive definite dense matrices. + +/*! The Epetra_SerialSymDenseMatrix class enables the construction and use of + real-valued, symmetric positive definite, + double-precision dense matrices. It is built on the Epetra_SerialDenseMatrix class which + in turn is built on the + BLAS via the Epetra_BLAS class. + +The Epetra_SerialSymDenseMatrix class is intended to provide full-featured support for solving +linear and eigen system +problems for symmetric positive definite matrices. It is written on top of BLAS and LAPACK +and thus has excellent +performance and numerical capabilities. Using this class, one can either perform simple +factorizations and solves or +apply all the tricks available in LAPACK to get the best possible solution for very +ill-conditioned problems. + +Epetra_SerialSymDenseMatrix vs. Epetra_LAPACK + +The Epetra_LAPACK class provides access to most of the same functionality as +Epetra_SerialSymDenseMatrix. +The primary difference is that Epetra_LAPACK is a "thin" layer on top of +LAPACK and Epetra_SerialSymDenseMatrix +attempts to provide easy access to the more sophisticated aspects of +solving dense linear and eigensystems. +
      +
    • When you should use Epetra_LAPACK: If you are simply looking for a + convenient wrapper around the Fortran LAPACK + routines and you have a well-conditioned problem, you should probably use Epetra_LAPACK directly. +
    • When you should use Epetra_SerialSymDenseMatrix: If you want to (or potentially want to) + solve ill-conditioned + problems or want to work with a more object-oriented interface, you should + probably use Epetra_SerialSymDenseMatrix. + +
    + +Constructing Epetra_SerialSymDenseMatrix Objects + +There are three Epetra_DenseMatrix constructors. The first constructs a zero-sized object +which should be made +to appropriate length using the Shape() or Reshape() functions and then filled with +the [] or () operators. +The second is a constructor that accepts user +data as a 2D array, the third is a copy constructor. The second constructor has +two data access modes (specified by the Epetra_DataAccess argument): +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the object. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +Extracting Data from Epetra_SerialSymDenseMatrix Objects + +Once a Epetra_SerialSymDenseMatrix is constructed, it is possible to view the data via access functions. + +\warning Use of these access functions cam be \e extremely dangerous from a data hiding perspective. + + +Vector and Utility Functions + +Once a Epetra_SerialSymDenseMatrix is constructed, several mathematical functions can be applied to +the object. Specifically: +
      +
    • Multiplication. +
    • Norms. +
    + +Counting floating point operations +The Epetra_SerialSymDenseMatrix class has Epetra_CompObject as a base class. Thus, floating +point operations +are counted and accumulated in the Epetra_Flop object (if any) that was set using the SetFlopCounter() +method in the Epetra_CompObject base class. + +*/ + +//========================================================================= +class Epetra_SerialSymDenseMatrix : public Epetra_SerialDenseMatrix { + + public: + //! @name Constructor/Destructor Methods + //@{ + //! Default constructor; defines a zero size object. + /*! + Epetra_SerialSymDenseMatrix objects defined by the default constructor + should be sized with the Shape() + or Reshape() functions. + Values should be defined by using the [] or ()operators. + + Note: By default the active part of the matrix is assumed to be in the lower triangle. + To set the upper part as active, call SetUpper(). + See Detailed Description section for further discussion. + */ + Epetra_SerialSymDenseMatrix(void); + //! Set object values from two-dimensional array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + A - Pointer to an array of double precision numbers. The first vector starts at A. + The second vector starts at A+LDA, the third at A+2*LDA, and so on. + \param In + LDA - The "Leading Dimension", or stride between vectors in memory. + \param In + NumRowsCols - Number of rows and columns in object. + + Note: By default the active part of the matrix is assumed to be in the lower triangle. + To set the upper part as active, call SetUpper(). + See Detailed Description section for further discussion. + */ + Epetra_SerialSymDenseMatrix(Epetra_DataAccess CV, double *A, int LDA, int NumRowsCols); + + //! Epetra_SerialSymDenseMatrix copy constructor. + + Epetra_SerialSymDenseMatrix(const Epetra_SerialSymDenseMatrix& Source); + + + //! Epetra_SerialSymDenseMatrix destructor. + virtual ~Epetra_SerialSymDenseMatrix (); + //@} + + //! @name Set Methods + //@{ + + //let the compiler know we intend to overload the base-class Shape function, + //rather than hide it. + using Epetra_SerialDenseMatrix::Shape; + + //! Set dimensions of a Epetra_SerialSymDenseMatrix object; init values to zero. + /*! + \param In + NumRowsCols - Number of rows and columns in object. + + Allows user to define the dimensions of a Epetra_DenseMatrix at any point. This function can + be called at any point after construction. Any values that were previously in this object are + destroyed and the resized matrix starts off with all zero values. + + \return Integer error code, set to 0 if successful. + */ + int Shape(int NumRowsCols) {return(Epetra_SerialDenseMatrix::Shape(NumRowsCols,NumRowsCols));}; + + //let the compiler know we intend to overload the base-class Reshape function, + //rather than hide it. + + using Epetra_SerialDenseMatrix::Reshape; + + //! Reshape a Epetra_SerialSymDenseMatrix object. + /*! + \param In + NumRowsCols - Number of rows and columns in object. + + Allows user to define the dimensions of a Epetra_SerialSymDenseMatrix at any point. This function can + be called at any point after construction. Any values that were previously in this object are + copied into the new shape. If the new shape is smaller than the original, the upper left portion + of the original matrix (the principal submatrix) is copied to the new matrix. + + \return Integer error code, set to 0 if successful. + */ + int Reshape(int NumRowsCols) {return(Epetra_SerialDenseMatrix::Reshape(NumRowsCols,NumRowsCols));}; + + + //! Specify that the lower triangle of the \e this matrix should be used. + void SetLower() {Upper_ = false; UPLO_ = 'L';}; + + //! Specify that the upper triangle of the \e this matrix should be used. + void SetUpper() {Upper_ = true; UPLO_ = 'U';}; + //@} + + //! @name Query methods + //@{ + + //! Returns true if upper triangle of \e this matrix has and will be used. + bool Upper() const {return(Upper_);}; + + //! Returns character value of UPLO used by LAPACK routines. + char UPLO() const {return(UPLO_);}; + //@} + + //! @name Mathematical Methods + //@{ + + //! Inplace scalar-matrix product A = \e a A. + /*! Scale a matrix, entry-by-entry using the value ScalarA. This method is sensitive to + the UPLO() parameter. + + + \param ScalarA (In) Scalar to multiply with A. + + \return Integer error code, set to 0 if successful. + + */ + int Scale ( double ScalarA ); + + + //! Computes the 1-Norm of the \e this matrix. + /*! + \return Integer error code, set to 0 if successful. + */ + double NormOne() const; + + //! Computes the Infinity-Norm of the \e this matrix. + double NormInf() const; + + //@} + + void CopyUPLOMat(bool Upper, double * A, int LDA, int NumRows); + + //! @name Deprecated methods (will be removed in later versions of this class) + //@{ + + //! Computes the 1-Norm of the \e this matrix (identical to NormOne() method). + /*! + \return Integer error code, set to 0 if successful. + */ + double OneNorm() const {return(Epetra_SerialSymDenseMatrix::NormOne());}; + + //! Computes the Infinity-Norm of the \e this matrix (identical to NormInf() method). + double InfNorm() const {return(Epetra_SerialSymDenseMatrix::NormInf());}; + //@} + + private: + + bool Upper_; + + char UPLO_; + + +}; + +#endif /* EPETRA_SERIALSYMDENSEMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_SrcDistObject.h b/fastlib/trilinos/include/Epetra_SrcDistObject.h new file mode 100644 index 0000000000..c67d6de1ee --- /dev/null +++ b/fastlib/trilinos/include/Epetra_SrcDistObject.h @@ -0,0 +1,64 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_SRCDISTOBJECT_H +#define EPETRA_SRCDISTOBJECT_H +class Epetra_BlockMap; + + +//! Epetra_SrcDistObject: A class for supporting flexible source distributed objects for import/export operations. + +/*! The Epetra_SrcDistObject is a base class for all Epetra distributed global objects that are potential + source objects for the general Epetra_DistObject class. It provides a way to send a very general distributed + object as the potential source object for an import or export object. For example, it is possible to pass + an Epetra_RowMatrix object as the source object for an import/export where the target is an Epetra_CrsMatrix, or + an Epetra_CrsGraph (where the RowMatrix values will be ignored). + +*/ + +//========================================================================== +class Epetra_SrcDistObject { + + public: + //! @name Destructor + //@{ + //! Epetra_SrcDistObject destructor. + virtual ~Epetra_SrcDistObject() {}; + //@} + + + //! @name Attribute accessor methods + //@{ + //! Returns a reference to the Epetra_BlockMap for this object. + virtual const Epetra_BlockMap & Map() const = 0; +}; + +#endif /* EPETRA_SRCDISTOBJECT_H */ diff --git a/fastlib/trilinos/include/Epetra_Time.h b/fastlib/trilinos/include/Epetra_Time.h new file mode 100644 index 0000000000..e5f949a263 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Time.h @@ -0,0 +1,117 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_TIME_H +#define EPETRA_TIME_H + +//! Epetra_Time: The Epetra Timing Class. +/*! The Epetra_Time class is a wrapper that encapsulates the general + information needed getting timing information. Currently it return + the elapsed time for each calling processor.. + A Epetra_Comm object is required for building all Epetra_Time objects. + + Epetra_Time support both serial execution and (via MPI) parallel + distributed memory execution. It is meant to insulate the user from + the specifics of timing across a variety of platforms. +*/ + +#include "Epetra_Object.h" +#include "Epetra_Comm.h" + +#ifdef EPETRA_MPI +#include "mpi.h" +#elif ICL +#include +#else +#include +#ifndef MINGW +#include +#endif +#endif + +class Epetra_Time: public Epetra_Object { + + public: + //! Epetra_Time Constructor. + /*! Creates a Epetra_Time instance. This instance can be queried for + elapsed time on the calling processor. StartTime is also set + for use with the ElapsedTime function. + */ + Epetra_Time(const Epetra_Comm & Comm); + + //! Epetra_Time Copy Constructor. + /*! Makes an exact copy of an existing Epetra_Time instance. + */ + Epetra_Time(const Epetra_Time& Time); + + //! Epetra_Time wall-clock time function. + /*! Returns the wall-clock time in seconds. A code section can be + timed by putting it between two calls to WallTime and taking the + difference of the times. + */ + double WallTime(void) const; + + //! Epetra_Time function to reset the start time for a timer object. + /*! Resets the start time for the timer object to the current time + A code section can be + timed by putting it between a call to ResetStartTime and ElapsedTime. + */ + void ResetStartTime(void); + + //! Epetra_Time elapsed time function. + /*! Returns the elapsed time in seconds since the timer object was + constructed, or since the ResetStartTime function was called. + A code section can be + timed by putting it between the Epetra_Time constructor and a call to + ElapsedTime, or between a call to ResetStartTime and ElapsedTime. + */ + double ElapsedTime(void) const; + + //! Epetra_Time Destructor. + /*! Completely deletes a Epetra_Time object. + */ + virtual ~Epetra_Time(void); + + Epetra_Time& operator=(const Epetra_Time& src) + { + StartTime_ = src.StartTime_; + Comm_ = src.Comm_; + return( *this ); + } + + private: + + double StartTime_; + const Epetra_Comm * Comm_; + +}; + +#endif /* EPETRA_TIME_H */ diff --git a/fastlib/trilinos/include/Epetra_Util.h b/fastlib/trilinos/include/Epetra_Util.h new file mode 100644 index 0000000000..faae67f367 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Util.h @@ -0,0 +1,290 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_UTIL_H +#define EPETRA_UTIL_H + +#include "Epetra_Object.h" +class Epetra_Map; +class Epetra_BlockMap; +class Epetra_CrsMatrix; +class Epetra_MultiVector; + +//! Epetra_Util: The Epetra Util Wrapper Class. +/*! The Epetra_Util class is a collection of useful functions that cut across a broad + set of other classes. +
      +
    • A random number generator is provided, along with methods to set and +retrieve the random-number seed. + +The random number generator is a multiplicative linear congruential generator, +with multiplier 16807 and modulus 2^31 - 1. It is based on the algorithm described in +"Random Number Generators: Good Ones Are Hard To Find", S. K. Park and K. W. Miller, +Communications of the ACM, vol. 31, no. 10, pp. 1192-1201. + +
    • Sorting is provided by a static function on this class (i.e., it is not +necessary to construct an instance of this class to use the Sort function). + +
    • A static function is provided for creating a new Epetra_Map object with + 1-to-1 ownership of entries from an existing map which may have entries that +appear on multiple processors. +
    + + Epetra_Util is a serial interface only. This is appropriate since the standard + utilities are only specified for serial execution (or shared memory parallel). +*/ +class Epetra_Util { + + public: + //! Epetra_Util Constructor. + /*! Builds an instance of a serial Util object. + */ + Epetra_Util(); + + + //! Epetra_Util Copy Constructor. + /*! Makes an exact copy of an existing Epetra_Util instance. + */ + Epetra_Util(const Epetra_Util& Util); + + //! Epetra_Util Destructor. + virtual ~Epetra_Util(); + + //! @name Random number utilities + //@{ + + //! Returns a random integer on the interval (0, 2^31-1) + unsigned int RandomInt(); + + //! Returns a random double on the interval (-1.0,1.0) + double RandomDouble(); + + //! Get seed from Random function. + /*! + \return Current random number seed. + */ + unsigned int Seed() const; + + //! Set seed for Random function. + /*! + \param In + Seed - An integer on the interval [1, 2^31-2] + + \return Integer error code, set to 0 if successful. + */ + int SetSeed(unsigned int Seed); + + //@} + + //! Epetra_Util Sort Routine (Shell sort) + /*! + + This function sorts a list of integer values in ascending or descending order. Additionally it sorts any + number of companion lists of doubles or ints. A shell sort is used, which is fast if indices are already sorted. + + \param In + SortAscending - Sort keys in ascending order if true, otherwise sort in descending order.. + \param In + NumKeys - Number of integer values to be sorted. + \param In/Out + Keys - List of integers to be sorted. + \param In + NumDoubleCompanions - Number of lists of double precision numbers to be sorted with the key. If set to zero, + DoubleCompanions is ignored and can be set to zero. + \param In + DoubleCompanions - DoubleCompanions[i] is a pointer to the ith list of doubles to be sorted with key. + \param In + NumIntCompanions - Number of lists of integers to be sorted with the key. If set to zero, + IntCompanions is ignored and can be set to zero. + \param In + IntCompanions - IntCompanions[i] is a pointer to the ith list of integers to be sorted with key. + + */ + static void Sort(bool SortAscending, int NumKeys, int * Keys, + int NumDoubleCompanions,double ** DoubleCompanions, + int NumIntCompanions, int ** IntCompanions); + + //! Epetra_Util Create_Root_Map function + /*! Function to create a new Epetra_Map object with all GIDs sent to the root processor + which is zero by default. All all processors will have no GIDs. This root map can then + be used to create an importer or exporter that will migrate all data to the root processor. + + If root is set to -1 then the user map will be replicated completely on all processors. + */ + static Epetra_Map Create_Root_Map(const Epetra_Map & usermap, + int root = 0); + + //! Epetra_Util Create_OneToOne_Map function + /*! Function to create a new Epetra_Map object with 1-to-1 ownership of + entries from an existing map which may have entries that appear on + multiple processors. + */ + static Epetra_Map Create_OneToOne_Map(const Epetra_Map& usermap, + bool high_rank_proc_owns_shared=false); + + //! Epetra_Util Create_OneToOne_Map function + /*! Function to create a new Epetra_Map object with 1-to-1 ownership of + entries from an existing map which may have entries that appear on + multiple processors. + */ + static Epetra_BlockMap Create_OneToOne_BlockMap(const Epetra_BlockMap& usermap, + bool high_rank_proc_owns_shared=false); + + //! Epetra_Util Chop method. Return zero if input Value is less than ChopValue + static double Chop(const double & Value){ + if (std::abs(Value) < chopVal_) return 0; + return Value; + }; + + static const double chopVal_; + + private: + unsigned int Seed_; +}; + + +// Epetra_Util constructor +inline Epetra_Util::Epetra_Util() : Seed_(std::rand()) {} +// Epetra_Util constructor +inline Epetra_Util::Epetra_Util(const Epetra_Util& Util) : Seed_(Util.Seed_) {} +// Epetra_Util destructor +inline Epetra_Util::~Epetra_Util(){} + +/** Utility function to perform a binary-search on a list of data. + Important assumption: data is assumed to be sorted. + + @param item to be searched for + @param list to be searched in + @param len Length of list + @param insertPoint Input/Output. If item is found, insertPoint is not + referenced. If item is not found, insertPoint is set to the offset at which + item should be inserted in list such that order (sortedness) would be + maintained. + @return offset Location in list at which item was found. -1 if not found. +*/ +int Epetra_Util_binary_search(int item, + const int* list, + int len, + int& insertPoint); + +/** Function to insert an item in a list, at a specified offset. + @return error-code 0 if successful, -1 if input parameters seem + unreasonable (offset > usedLength, offset<0, etc). + + @param item to be inserted + @param offset location at which to insert item + @param list array into which item is to be inserted. This array may be + re-allocated by this function. + @param usedLength number of items already present in list. Will be updated + to reflect the new length. + @param allocatedLength current allocated length of list. Will be updated + to reflect the new allocated-length, if applicable. Re-allocation + occurs only if usedLength==allocatedLength on entry. + @param allocChunkSize Optional argument, defaults to 32. Increment by + which the array should be expanded, if re-allocation is necessary. + @return error-code 0 if successful. -1 if input parameters don't make sense. + */ +template +int Epetra_Util_insert(T item, int offset, T*& list, + int& usedLength, + int& allocatedLength, + int allocChunkSize=32) +{ + if (offset < 0 || offset > usedLength) { + return(-1); + } + + if (usedLength < allocatedLength) { + for(int i=usedLength; i>offset; --i) { + list[i] = list[i-1]; + } + list[offset] = item; + ++usedLength; + return(0); + } + + T* newlist = new T[allocatedLength+allocChunkSize]; + if (newlist == NULL) { + return(-1); + } + + allocatedLength += allocChunkSize; + int i; + for(i=0; i +#include +#include +#include +#include +#include +#include +class Epetra_BlockMap; +class Epetra_Map; +class Epetra_Import; +class Epetra_Export; +class Epetra_Vector; +class Epetra_MultiVector; + +//! Epetra_VbrMatrix: A class for the construction and use of real-valued double-precision variable block-row sparse matrices. +/*! The Epetra_VbrMatrix class is a sparse variable block row matrix object. This matrix can be + used in a parallel setting, with data distribution described by Epetra_Map attributes. + The structure or graph of the matrix is defined by an Epetra_CrsGraph attribute. + + In addition to coefficient access, the primary operations provided by Epetra_VbrMatrix are matrix + times vector and matrix times multi-vector multiplication. +

    +Creating and filling Epetra_VbrMatrix objects + +Constructing Epetra_VbrMatrix objects is a multi-step process. The basic steps are as follows: +

      +
    1. Create Epetra_VbrMatrix instance via one of the constructors: +
        +
      • Constructor that accepts one Epetra_Map object, a row-map defining the distribution of matrix rows. +
      • Constructor that accepts two Epetra_Map objects. (The second map is a column-map, and describes the set + of column-indices that appear in each processor's portion of the matrix. Generally these are + overlapping sets -- column-indices may appear on more than one processor.) +
      • Constructor that accepts an Epetra_CrsGraph object, defining the non-zero structure of the matrix. +
      +
    2. Input coefficient values (more detail on this below). +
    3. Complete construction by calling FillComplete. +
    + +Note that even after FillComplete() has been called, it is possible to update existing matrix +entries but it is \e not possible to create new entries. +

    + +Epetra_Map attributes + +Epetra_VbrMatrix objects have four Epetra_Map attributes, which are held by the Epetra_CrsGraph attribute. + +The Epetra_Map attributes can be obtained via these accessor methods: +

      +
    • RowMap() Describes the numbering and distribution of the rows of the matrix. The row-map exists and is valid + for the entire life of the matrix. The set of matrix rows is defined by the row-map and may not be changed. Rows + may not be inserted or deleted by the user. The only change that may be made is that the user can replace the + row-map with a compatible row-map (which is the same except for re-numbering) by calling the ReplaceRowMap() method. +
    • ColMap() Describes the set of column-indices that appear in the rows in each processor's portion of the matrix. + Unless provided by the user at construction time, a valid column-map doesn't exist until FillComplete() is called. +
    • RangeMap() Describes the range of the matrix operator. e.g., for a matrix-vector product operation, the result + vector's map must be compatible with the range-map of this matrix. The range-map is usually the same as the row-map. + The range-map is set equal to the row-map at matrix creation time, but may be specified by the user when + FillComplete() is called. +
    • DomainMap() Describes the domain of the matrix operator. The domain-map can be specified by the user when + FillComplete() is called. Until then, it is set equal to the row-map. +
    + +It is important to note that while the row-map and the range-map are often the same, the column-map and the domain-map +are almost never the same. The set of entries in a distributed column-map almost always form overlapping sets, with +entries being associated with more than one processor. A domain-map, on the other hand, must be a 1-to-1 map, with +entries being associated with only a single processor. + +Local versus Global Indices + +Epetra_VbrMatrix has query functions IndicesAreLocal() and IndicesAreGlobal(), which are used to determine whether the +underlying Epetra_CrsGraph attribute's column-indices have been transformed into a local index space or not. (This +transformation occurs when the method Epetra_CrsGraph::FillComplete() is called, which happens when +the method Epetra_VbrMatrix::FillComplete() is called.) The state of the indices in the +graph determines the behavior of many Epetra_VbrMatrix methods. If an Epetra_VbrMatrix instance is constructed using +one of the constructors that does not accept a pre-existing Epetra_CrsGraph object, then an Epetra_CrsGraph attribute +is created internally and its indices remain untransformed (IndicesAreGlobal()==true) until Epetra_VbrMatrix::FillComplete() +is called. The query function Epetra_VbrMatrix::Filled() returns true if Epetra_VbrMatrix::FillComplete() has been +called. + +Inputting coefficient values + +The process for inputting block-entry coefficients is as follows: +
      +
    1. Indicate that values for a specified row are about to be provided by calling one of these methods + which specify a block-row and a list of block-column-indices: +
        +
      • BeginInsertGlobalValues() +
      • BeginInsertMyValues() +
      • BeginReplaceGlobalValues() +
      • BeginReplaceMyValues() +
      • BeginSumIntoGlobalValues() +
      • BeginSumIntoMyValues() +
      +
    2. Loop over the list of block-column-indices and pass each block-entry to the matrix using the + method SubmitBlockEntry(). +
    3. Complete the process for the specified block-row by calling the method EndSubmitEntries(). +
    + +Note that the 'GlobalValues' methods have the precondition that IndicesAreGlobal() must be true, and +the 'MyValues' methods have the precondition that IndicesAreLocal() must be true. Furthermore, the +'SumInto' and 'Replace' methods may only be used to update matrix entries which already exist, and +the 'Insert' methods may only be used if IndicesAreContiguous() is false. + + Counting Floating Point Operations + +Each Epetra_VbrMatrix object keeps track of the number of \e serial floating point operations +performed using the specified object as the \e this argument to the function. The Flops() +function returns this number as a double precision number. Using this information, in +conjunction with the Epetra_Time class, one can get accurate parallel performance +numbers. The ResetFlops() function resets the floating point counter. + +*/ + +class Epetra_VbrMatrix : public Epetra_DistObject, + public Epetra_CompObject, + public Epetra_BLAS, + public virtual Epetra_RowMatrix { + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_VbrMatrix constuctor with variable number of indices per row. + /*! Creates a Epetra_VbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - A Epetra_BlockMap listing the block rows that this processor will contribute to. + \param In + NumBlockEntriesPerRow - An integer array of length NumRows + such that NumBlockEntriesPerRow[i] indicates the (approximate) number of Block entries in the ith row. + */ + Epetra_VbrMatrix(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, int *NumBlockEntriesPerRow); + + //! Epetra_VbrMatrix constuctor with fixed number of indices per row. + /*! Creates a Epetra_VbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - An Epetra_BlockMap listing the block rows that this processor will contribute to. + \param In + NumBlockEntriesPerRow - An integer that indicates the (approximate) number of Block entries in the each Block row. + Note that it is possible to use 0 for this value and let fill occur during the insertion phase. + + */ + Epetra_VbrMatrix(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, int NumBlockEntriesPerRow); + + //! Epetra_VbrMatrix constuctor with variable number of indices per row. + /*! Creates a Epetra_VbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - A Epetra_BlockMap listing the block rows that this processor will contribute to. + \param In + ColMap - A Epetra_BlockMap. + \param In + NumBlockEntriesPerRow - An integer array of length NumRows + such that NumBlockEntriesPerRow[i] indicates the (approximate) number of Block entries in the ith row. + */ + Epetra_VbrMatrix(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, const Epetra_BlockMap& ColMap, int *NumBlockEntriesPerRow); + + //! Epetra_VbrMatrix constuctor with fixed number of indices per row. + /*! Creates a Epetra_VbrMatrix object and allocates storage. + + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + RowMap - A Epetra_BlockMap listing the block rows that this processor will contribute to. + \param In + ColMap - An Epetra_BlockMap listing the block columns that this processor will contribute to. + \param In + NumBlockEntriesPerRow - An integer that indicates the (approximate) number of Block entries in the each Block row. + Note that it is possible to use 0 for this value and let fill occur during the insertion phase. + + */ + Epetra_VbrMatrix(Epetra_DataAccess CV, const Epetra_BlockMap& RowMap, const Epetra_BlockMap& ColMap, int NumBlockEntriesPerRow); + + //! Construct a matrix using an existing Epetra_CrsGraph object. + /*! Allows the nonzero structure from another matrix, or a structure that was + constructed independently, to be used for this matrix. + \param In + CV - A Epetra_DataAccess enumerated type set to Copy or View. + \param In + Graph - A Epetra_CrsGraph object, extracted from another Epetra matrix object or constructed directly from + using the Epetra_CrsGraph constructors. + */ + + Epetra_VbrMatrix(Epetra_DataAccess CV, const Epetra_CrsGraph & Graph); + + //! Copy constructor. + Epetra_VbrMatrix(const Epetra_VbrMatrix & Matrix); + + //! Epetra_VbrMatrix Destructor + virtual ~Epetra_VbrMatrix(); + //@} + + //! @name Insertion/Replace/SumInto methods + //@{ + + Epetra_VbrMatrix& operator=(const Epetra_VbrMatrix& src); + + //! Initialize all values in graph of the matrix with constant value. + /*! + \param In + ScalarConstant - Value to use. + + \return Integer error code, set to 0 if successful. + */ + int PutScalar(double ScalarConstant); + + //! Multiply all values in the matrix by a constant value (in place: A <- ScalarConstant * A). + /*! + \param In + ScalarConstant - Value to use. + + \return Integer error code, set to 0 if successful. + */ + int Scale(double ScalarConstant); + + + //! Initiate insertion of a list of elements in a given global row of the matrix, values are inserted via SubmitEntry(). + /*! + \param In + BlockRow - Block Row number (in global coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginInsertGlobalValues(int BlockRow, + int NumBlockEntries, + int * BlockIndices); + + //! Initiate insertion of a list of elements in a given local row of the matrix, values are inserted via SubmitEntry(). + /*! + \param In + BlockRow - Block Row number (in local coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginInsertMyValues(int BlockRow, int NumBlockEntries, int * BlockIndices); + + //! Initiate replacement of current values with this list of entries for a given global row of the matrix, values are replaced via SubmitEntry() + /*! + \param In + Row - Block Row number (in global coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginReplaceGlobalValues(int BlockRow, int NumBlockEntries, int *BlockIndices); + + //! Initiate replacement of current values with this list of entries for a given local row of the matrix, values are replaced via SubmitEntry() + /*! + \param In + Row - Block Row number (in local coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginReplaceMyValues(int BlockRow, int NumBlockEntries, int *BlockIndices); + + //! Initiate summing into current values with this list of entries for a given global row of the matrix, values are replaced via SubmitEntry() + /*! + \param In + Row - Block Row number (in global coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Global column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginSumIntoGlobalValues(int BlockRow, int NumBlockEntries, int *BlockIndices); + + //! Initiate summing into current values with this list of entries for a given local row of the matrix, values are replaced via SubmitEntry() + /*! + \param In + Row - Block Row number (in local coordinates) to put elements. + \param In + NumBlockEntries - Number of entries. + \param In + Indices - Local column indices corresponding to values. + + \return Integer error code, set to 0 if successful. + */ + int BeginSumIntoMyValues(int BlockRow, int NumBlockEntries, int *BlockIndices); + + //! Submit a block entry to the indicated block row and column specified in the Begin routine. + /* Submit a block entry that will recorded in the block row that was initiated by one of the + Begin routines listed above. Once a one of the following routines: BeginInsertGlobalValues(), + BeginInsertMyValues(), BeginReplaceGlobalValues(), BeginReplaceMyValues(), BeginSumIntoGlobalValues(), + BeginSumIntoMyValues(), you \e must call SubmitBlockEntry() NumBlockEntries times to register the values + corresponding to the block indices passed in to the Begin routine. If the Epetra_VbrMatrix constuctor + was called in Copy mode, the values will be copied. However, no copying will be done until the EndSubmitEntries() + function is call to complete submission of the current block row. If the constructor was called in View mode, all + block entries passed via SubmitBlockEntry() will not be copied, but a pointer will be set to point to the argument Values + that was passed in by the user. + + For performance reasons, SubmitBlockEntry() does minimal processing of data. Any processing that can be + delayed is performed in EndSubmitEntries(). + + \param In + Values - The starting address of the values. + \param In + LDA - The stride between successive columns of Values. + \param In + NumRows - The number of rows passed in. + \param In + NumCols - The number of columns passed in. + + \return Integer error code, set to 0 if successful. + */ + int SubmitBlockEntry(double *Values, int LDA, int NumRows, int NumCols); + + //! Submit a block entry to the indicated block row and column specified in the Begin routine. + /* Submit a block entry that will recorded in the block row that was initiated by one of the + Begin routines listed above. Once a one of the following routines: BeginInsertGlobalValues(), + BeginInsertMyValues(), BeginReplaceGlobalValues(), BeginReplaceMyValues(), BeginSumIntoGlobalValues(), + BeginSumIntoMyValues(), you \e must call SubmitBlockEntry() NumBlockEntries times to register the values + corresponding to the block indices passed in to the Begin routine. If the Epetra_VbrMatrix constuctor + was called in Copy mode, the values will be copied. However, no copying will be done until the EndSubmitEntries() + function is call to complete submission of the current block row. If the constructor was called in View mode, all + block entries passed via SubmitBlockEntry() will not be copied, but a pointer will be set to point to the argument Values + that was passed in by the user. + + For performance reasons, SubmitBlockEntry() does minimal processing of data. Any processing that can be + delayed is performed in EndSubmitEntries(). + + \param In + Mat - Preformed dense matrix block. + + \return Integer error code, set to 0 if successful. + */ + int SubmitBlockEntry( Epetra_SerialDenseMatrix &Mat ); + + //! Completes processing of all data passed in for the current block row. + /*! This function completes the processing of all block entries submitted via SubmitBlockEntry(). + It also checks to make sure that SubmitBlockEntry was called the correct number of times as + specified by the Begin routine that initiated the entry process. + */ + + int EndSubmitEntries(); + + //! Replaces diagonal values of the with those in the user-provided vector. + /*! This routine is meant to allow replacement of {\bf existing} diagonal values. + If a diagonal value does not exist for a given row, the corresponding value in + the input Epetra_Vector will be ignored and the return code will be set to 1. + + The Epetra_Map associated with the input Epetra_Vector must be compatible with + the RowMap of the matrix. + + \param Diagonal (In) - New values to be placed in the main diagonal. + + \return Integer error code, set to 0 if successful, 1 of one or more diagonal entries not present in matrix. + */ + int ReplaceDiagonalValues(const Epetra_Vector & Diagonal); + + //! Signal that data entry is complete, perform transformations to local index space. + /* This version of FillComplete assumes that the domain and range + distributions are identical to the matrix row distributions. + \return error code, 0 if successful. Returns a positive warning code of 3 + if the matrix is rectangular (meaning that the other overloading of + FillComplete should have been called, with differen domain-map and + range-map specified). + */ + int FillComplete(); + + //! Signal that data entry is complete, perform transformations to local index space. + /* This version of FillComplete requires the explicit specification of the domain + and range distribution maps. These maps are used for importing and exporting vector + and multi-vector elements that are needed for distributed matrix computations. For + example, to compute y = Ax in parallel, we would specify the DomainMap as the distribution + of the vector x and the RangeMap as the distribution of the vector y. + \param In + DomainMap - Map that describes the distribution of vector and multi-vectors in the + matrix domain. + \param In + RangeMap - Map that describes the distribution of vector and multi-vectors in the + matrix range. + + \return error code, 0 if successful. positive warning code of 2 if it is detected that the + matrix-graph got out of sync since this matrix was constructed (for instance if + graph.FillComplete() was called by another matrix that shares the graph) + */ + int FillComplete(const Epetra_BlockMap& DomainMap, const Epetra_BlockMap& RangeMap); + + //! If FillComplete() has been called, this query returns true, otherwise it returns false. + bool Filled() const {return(Graph_->Filled());}; + //@} + + //! @name Extraction methods + //@{ + + //! Copy the block indices into user-provided array, set pointers for rest of data for specified global block row. + /*! + This function provides the lightest weight approach to accessing a global block row when the matrix may be + be stored in local or global index space. In other words, this function will always work because the block + indices are returned in user-provided space. All other array arguments are independent of whether or not + indices are local or global. Other than the BlockIndices array, all other array argument are returned as + pointers to internal data. + + \param In + BlockRow - Global block row to extract. + \param In + MaxNumBlockEntries - Length of user-provided BlockIndices array. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries actually extracted. + \param Out + BlockIndices - Extracted global column indices for the corresponding block entries. + \param Out + Values - Pointer to list of pointers to block entries. Note that the actual values are not copied. + + \return Integer error code, set to 0 if successful. + */ + int ExtractGlobalBlockRowPointers(int BlockRow, int MaxNumBlockEntries, + int & RowDim, int & NumBlockEntries, + int * BlockIndices, + Epetra_SerialDenseMatrix ** & Values) const; + + //! Copy the block indices into user-provided array, set pointers for rest of data for specified local block row. + /*! + This function provides the lightest weight approach to accessing a local block row when the matrix may be + be stored in local or global index space. In other words, this function will always work because the block + indices are returned in user-provided space. All other array arguments are independent of whether or not + indices are local or global. Other than the BlockIndices array, all other array argument are returned as + pointers to internal data. + + \param In + BlockRow - Local block row to extract. + \param In + MaxNumBlockEntries - Length of user-provided BlockIndices array. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries actually extracted. + \param Out + BlockIndices - Extracted local column indices for the corresponding block entries. + \param Out + Values - Pointer to list of pointers to block entries. Note that the actual values are not copied. + + \return Integer error code, set to 0 if successful. + */ + int ExtractMyBlockRowPointers(int BlockRow, int MaxNumBlockEntries, + int & RowDim, int & NumBlockEntries, + int * BlockIndices, + Epetra_SerialDenseMatrix** & Values) const; + + //! Initiates a copy of the specified global row in user-provided arrays. + /*! + \param In + BlockRow - Global block row to extract. + \param In + MaxNumBlockEntries - Length of user-provided BlockIndices, ColDims, and LDAs arrays. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries actually extracted. + \param Out + BlockIndices - Extracted global column indices for the corresponding block entries. + \param Out + ColDim - List of column dimensions for each corresponding block entry that will be extracted. + + \return Integer error code, set to 0 if successful. + */ + int BeginExtractGlobalBlockRowCopy(int BlockRow, int MaxNumBlockEntries, + int & RowDim, int & NumBlockEntries, + int * BlockIndices, int * ColDims) const; + + //! Initiates a copy of the specified local row in user-provided arrays. + /*! + \param In + BlockRow - Local block row to extract. + \param In + MaxNumBlockEntries - Length of user-provided BlockIndices, ColDims, and LDAs arrays. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries actually extracted. + \param Out + BlockIndices - Extracted local column indices for the corresponding block entries. + \param Out + ColDim - List of column dimensions for each corresponding block entry that will be extracted. + + \return Integer error code, set to 0 if successful. + */ + int BeginExtractMyBlockRowCopy(int BlockRow, int MaxNumBlockEntries, + int & RowDim, int & NumBlockEntries, + int * BlockIndices, int * ColDims) const; + + //! Extract a copy of an entry from the block row specified by one of the BeginExtract routines. + /*! Once BeginExtractGlobalBlockRowCopy() or BeginExtractMyBlockRowCopy() is called, you can extract + the block entries of specified block row one-entry-at-a-time. The entries will be extracted + in an order corresponding to the BlockIndices list that was returned by the BeginExtract routine. + + \param In + SizeOfValues - Amount of memory associated with Values. This must be at least as big as + LDA*NumCol, where NumCol is the column dimension of the block entry being copied + \param InOut + Values - Starting location where the block entry will be copied. + \param In + LDA - Specifies the stride that will be used when copying columns into Values. + \param In + SumInto - If set to true, the block entry values will be summed into existing values. + */ + + int ExtractEntryCopy(int SizeOfValues, double * Values, int LDA, bool SumInto) const; + + //! Initiates a view of the specified global row, only works if matrix indices are in global mode. + /*! + \param In + BlockRow - Global block row to view. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries to be viewed. + \param Out + BlockIndices - Pointer to global column indices for the corresponding block entries. + + \return Integer error code, set to 0 if successful. + */ + int BeginExtractGlobalBlockRowView(int BlockRow, int & RowDim, int & NumBlockEntries, + int * & BlockIndices) const; + + //! Initiates a view of the specified local row, only works if matrix indices are in local mode. + /*! + \param In + BlockRow - Local block row to view. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries to be viewed. + \param Out + BlockIndices - Pointer to local column indices for the corresponding block entries. + + \return Integer error code, set to 0 if successful. + */ + int BeginExtractMyBlockRowView(int BlockRow, int & RowDim, int & NumBlockEntries, + int * & BlockIndices) const; + + + //! Returns a pointer to the current block entry. + /*! After a call to BeginExtractGlobal() or BlockRowViewBeginExtractMyBlockRowView(), + ExtractEntryView() can be called up to NumBlockEntries times to get each block entry in the + specified block row. + \param InOut + entry - A pointer that will be set to the current block entry. + */ + + int ExtractEntryView(Epetra_SerialDenseMatrix* & entry) const; + + //! Initiates a view of the specified global row, only works if matrix indices are in global mode. + /*! + \param In + BlockRow - Global block row to view. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries to be viewed. + \param Out + BlockIndices - Pointer to global column indices for the corresponding block entries. + \param Out + Values - Pointer to an array of pointers to the block entries in the specified block row. + + \return Integer error code, set to 0 if successful. + */ + int ExtractGlobalBlockRowView(int BlockRow, int & RowDim, int & NumBlockEntries, + int * & BlockIndices, + Epetra_SerialDenseMatrix** & Values) const; + + //! Initiates a view of the specified local row, only works if matrix indices are in local mode. + /*! + \param In + BlockRow - Local block row to view. + \param Out + RowDim - Number of equations in the requested block row. + \param Out + NumBlockEntries - Number of nonzero entries to be viewed. + \param Out + BlockIndices - Pointer to local column indices for the corresponding block entries. + \param Out + Values - Pointer to an array of pointers to the block entries in the specified block row. + + \return Integer error code, set to 0 if successful. + */ + int ExtractMyBlockRowView(int BlockRow, int & RowDim, int & NumBlockEntries, + int * & BlockIndices, + Epetra_SerialDenseMatrix** & Values) const; + + + //! Returns a copy of the main diagonal in a user-provided vector. + /*! + \param Out + Diagonal - Extracted main diagonal. + + \return Integer error code, set to 0 if successful. + */ + int ExtractDiagonalCopy(Epetra_Vector & Diagonal) const; + + //! Initiates a copy of the block diagonal entries to user-provided arrays. + /*! + \param In + MaxNumBlockDiagonalEntries - Length of user-provided RowColDims array. + \param Out + NumBlockDiagonalEntries - Number of block diagonal entries that can actually be extracted. + \param Out + RowColDim - List of row and column dimension for corresponding block diagonal entries. + + \return Integer error code, set to 0 if successful. + */ + int BeginExtractBlockDiagonalCopy(int MaxNumBlockDiagonalEntries, + int & NumBlockDiagonalEntries, int * RowColDims ) const; + //! Extract a copy of a block diagonal entry from the matrix. + /*! Once BeginExtractBlockDiagonalCopy() is called, you can extract + the block diagonal entries one-entry-at-a-time. The entries will be extracted + in ascending order. + + \param In + SizeOfValues - Amount of memory associated with Values. This must be at least as big as + LDA*NumCol, where NumCol is the column dimension of the block entry being copied + \param InOut + Values - Starting location where the block entry will be copied. + \param In + LDA - Specifies the stride that will be used when copying columns into Values. + \param In + SumInto - If set to true, the block entry values will be summed into existing values. + */ + + int ExtractBlockDiagonalEntryCopy(int SizeOfValues, double * Values, int LDA, bool SumInto) const; + + //! Initiates a view of the block diagonal entries. + /*! + \param Out + NumBlockDiagonalEntries - Number of block diagonal entries that can be viewed. + \param Out + RowColDim - Pointer to list of row and column dimension for corresponding block diagonal entries. + + \return Integer error code, set to 0 if successful. + */ + int BeginExtractBlockDiagonalView(int & NumBlockDiagonalEntries, int * & RowColDims ) const; + + //! Extract a view of a block diagonal entry from the matrix. + /*! Once BeginExtractBlockDiagonalView() is called, you can extract a view of + the block diagonal entries one-entry-at-a-time. The views will be extracted + in ascending order. + + \param Out + Values - Pointer to internal copy of block entry. + \param Out + LDA - Column stride of Values. + */ + + int ExtractBlockDiagonalEntryView(double * & Values, int & LDA) const; + //@} + + //! @name Computational methods + //@{ + + + //! Returns the result of a Epetra_VbrMatrix multiplied by a Epetra_Vector x in y. + /*! + \param In + TransA - If true, multiply by the transpose of matrix, otherwise just use matrix. + \param In + x - A Epetra_Vector to multiply by. + \param Out + y - A Epetra_Vector containing result. + + \return Integer error code, set to 0 if successful. + */ + int Multiply1(bool TransA, const Epetra_Vector& x, Epetra_Vector& y) const; + + //! Returns the result of a Epetra_VbrMatrix multiplied by a Epetra_MultiVector X in Y. + /*! + \param In + TransA -If true, multiply by the transpose of matrix, otherwise just use matrix. + \param In + X - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Out + Y -A Epetra_MultiVector of dimension NumVectorscontaining result. + + \return Integer error code, set to 0 if successful. + */ + int Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + //! Returns the result of a solve using the Epetra_VbrMatrix on a Epetra_Vector x in y. + /*! + \param In + Upper -If true, solve Ux = y, otherwise solve Lx = y. + \param In + Trans -If true, solve transpose problem. + \param In + UnitDiagonal -If true, assume diagonal is unit (whether it's stored or not). + \param In + x -A Epetra_Vector to solve for. + \param Out + y -A Epetra_Vector containing result. + + \return Integer error code, set to 0 if successful. + */ + int Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_Vector& x, Epetra_Vector& y) const; + + //! Returns the result of a Epetra_VbrMatrix multiplied by a Epetra_MultiVector X in Y. + /*! + \param In + Upper -If true, solve Ux = y, otherwise solve Lx = y. + \param In + Trans -If true, solve transpose problem. + \param In + UnitDiagonal -If true, assume diagonal is unit (whether it's stored or not). + \param In + X - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + int Solve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + + //! Computes the sum of absolute values of the rows of the Epetra_VbrMatrix, results returned in x. + /*! The vector x will return such that x[i] will contain the inverse of sum of the absolute values of the + \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. Using the resulting vector from this function as input to LeftScale() + will make the infinity norm of the resulting matrix exactly 1. + \param Out + x -A Epetra_Vector containing the row sums of the \e this matrix. + \warning It is assumed that the distribution of x is the same as the rows of \e this. + + \return Integer error code, set to 0 if successful. + */ + int InvRowSums(Epetra_Vector& x) const; + + //! Scales the Epetra_VbrMatrix on the left with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the row number of A + and j denotes the column number of A. + \param In + x -A Epetra_Vector to solve for. + + \return Integer error code, set to 0 if successful. + */ + int LeftScale(const Epetra_Vector& x); + + //! Computes the sum of absolute values of the columns of the Epetra_VbrMatrix, results returned in x. + /*! The vector x will return such that x[j] will contain the inverse of sum of the absolute values of the + \e this matrix will be sca such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. Using the resulting vector from this function as input to + RighttScale() will make the one norm of the resulting matrix exactly 1. + \param Out + x -A Epetra_Vector containing the column sums of the \e this matrix. + \warning It is assumed that the distribution of x is the same as the rows of \e this. + + \return Integer error code, set to 0 if successful. + */ + int InvColSums(Epetra_Vector& x) const ; + + //! Scales the Epetra_VbrMatrix on the right with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. + \param In + x -The Epetra_Vector used for scaling \e this. + + \return Integer error code, set to 0 if successful. + */ + int RightScale(const Epetra_Vector& x); + //@} + + //! @name Matrix Properties Query Methods + //@{ + + //! Eliminates memory that is used for construction. Make consecutive row index sections contiguous. + int OptimizeStorage(); + + //! If OptimizeStorage() has been called, this query returns true, otherwise it returns false. + bool StorageOptimized() const {return(StorageOptimized_);}; + + //! If matrix indices has not been transformed to local, this query returns true, otherwise it returns false. + bool IndicesAreGlobal() const {return(Graph_->IndicesAreGlobal());}; + + //! If matrix indices has been transformed to local, this query returns true, otherwise it returns false. + bool IndicesAreLocal() const {return(Graph_->IndicesAreLocal());}; + + //! If matrix indices are packed into single array (done in OptimizeStorage()) return true, otherwise false. + bool IndicesAreContiguous() const {return(Graph_->IndicesAreContiguous());}; + + //! If matrix is lower triangular in local index space, this query returns true, otherwise it returns false. + bool LowerTriangular() const {return(Graph_->LowerTriangular());}; + + //! If matrix is upper triangular in local index space, this query returns true, otherwise it returns false. + bool UpperTriangular() const {return(Graph_->UpperTriangular());}; + + //! If matrix has no diagonal entries based on global row/column index comparisons, this query returns true, otherwise it returns false. + bool NoDiagonal() const {return(Graph_->NoDiagonal());}; + + //@} + + //! @name Atribute access functions + //@{ + + //! Returns the infinity norm of the global matrix. + /* Returns the quantity \f$ \| A \|_\infty\f$ such that + \f[\| A \|_\infty = \max_{1\lei\lem} \sum_{j=1}^n |a_{ij}| \f]. + \warning The NormInf() method will not properly calculate the infinity norm for a matrix that has entries that are + replicated on multiple processors. */ + double NormInf() const; + + //! Returns the one norm of the global matrix. + /* Returns the quantity \f$ \| A \|_1\f$ such that + \f[\| A \|_1 = \max_{1\lej\len} \sum_{i=1}^m |a_{ij}| \f]. + \warning The NormOne() method will not properly calculate the one norm for a matrix that has entries that are + */ + double NormOne() const; + + //! Returns the frobenius norm of the global matrix. + /* Returns the quantity \f[ \| A \|_{Frobenius} = \sqrt{\sum_{i=1}^m \sum_{j=1}^n\|a_{ij}\|^2}\f] + \warning the NormFrobenius() method will not properly calculate the frobenius norm for a matrix that + has entries which are replicated on multiple processors. In that case, the returned + norm will be larger than the true norm. + */ + double NormFrobenius() const; + + //! Returns the maximum row dimension of all block entries on this processor. + int MaxRowDim() const {return(Graph_->MaxRowDim());}; + + //! Returns the maximum column dimension of all block entries on this processor. + int MaxColDim() const {return(Graph_->MaxColDim());}; + + //! Returns the maximum row dimension of all block entries across all processors. + int GlobalMaxRowDim() const {return(Graph_->GlobalMaxRowDim());}; + + //! Returns the maximum column dimension of all block entries across all processors. + int GlobalMaxColDim() const {return(Graph_->GlobalMaxColDim());}; + + //! Returns the number of matrix rows owned by the calling processor. + int NumMyRows() const {return(Graph_->NumMyRows());}; + //! Returns the number of matrix columns owned by the calling processor. + int NumMyCols() const {return(Graph_->NumMyCols());}; + + //! Returns the number of nonzero entriesowned by the calling processor . + int NumMyNonzeros() const {return(Graph_->NumMyNonzeros());}; + + //! Returns the number of global matrix rows. + int NumGlobalRows() const {return(Graph_->NumGlobalRows());}; + + //! Returns the number of global matrix columns. + int NumGlobalCols() const {return(Graph_->NumGlobalCols());}; + + //! Returns the number of nonzero entries in the global matrix. + /* + Note that if maps are defined such that some nonzeros appear on + multiple processors, then those nonzeros will be counted multiple + times. If the user wishes to assemble a matrix from overlapping + submatrices, they can use Epetra_FEVbrMatrix. + */ + int NumGlobalNonzeros() const {return(Graph_->NumGlobalNonzeros());}; + + //! Returns the number of Block matrix rows owned by the calling processor. + int NumMyBlockRows() const {return(Graph_->NumMyBlockRows());}; + + //! Returns the number of Block matrix columns owned by the calling processor. + int NumMyBlockCols() const {return(Graph_->NumMyBlockCols());}; + + //! Returns the number of nonzero block entries in the calling processor's portion of the matrix. + int NumMyBlockEntries() const {return(Graph_->NumMyEntries());}; + + //! Returns the number of local nonzero block diagonal entries, based on global row/column index comparisons. + int NumMyBlockDiagonals() const {return(Graph_->NumMyBlockDiagonals());}; + + //! Returns the number of local nonzero diagonal entries, based on global row/column index comparisons. + int NumMyDiagonals() const {return(Graph_->NumMyDiagonals());}; + + //! Returns the number of global Block matrix rows. + int NumGlobalBlockRows() const {return(Graph_->NumGlobalBlockRows());}; + + //! Returns the number of global Block matrix columns. + int NumGlobalBlockCols() const {return(Graph_->NumGlobalBlockCols());}; + + //! Returns the number of nonzero block entries in the global matrix. + int NumGlobalBlockEntries() const {return(Graph_->NumGlobalEntries());}; + + //! Returns the number of global nonzero block diagonal entries, based on global row/column index comparisions. + int NumGlobalBlockDiagonals() const {return(Graph_->NumGlobalBlockDiagonals());}; + + //! Returns the number of global nonzero diagonal entries, based on global row/column index comparisions. + int NumGlobalDiagonals() const {return(Graph_->NumGlobalDiagonals());}; + + //! Returns the current number of nonzero Block entries in specified global row on this processor. + int NumGlobalBlockEntries(int Row) const {return(Graph_->NumGlobalIndices(Row));}; + + //! Returns the allocated number of nonzero Block entries in specified global row on this processor. + int NumAllocatedGlobalBlockEntries(int Row) const{return(Graph_->NumAllocatedGlobalIndices(Row));}; + + //! Returns the maximum number of nonzero entries across all rows on this processor. + int MaxNumBlockEntries() const {return(Graph_->MaxNumIndices());}; + + //! Returns the maximum number of nonzero entries across all rows on this processor. + int GlobalMaxNumBlockEntries() const {return(Graph_->GlobalMaxNumIndices());}; + + //! Returns the current number of nonzero Block entries in specified local row on this processor. + int NumMyBlockEntries(int Row) const {return(Graph_->NumMyIndices(Row));}; + + //! Returns the allocated number of nonzero Block entries in specified local row on this processor. + int NumAllocatedMyBlockEntries(int Row) const {return(Graph_->NumAllocatedMyIndices(Row));}; + + //! Returns the maximum number of nonzero entries across all block rows on this processor. + /*! Let ki = the number of nonzero values in the ith block row of the VbrMatrix object. For example, + if the ith block row had 5 block entries and the size of each entry was 4-by-4, ki would be 80. + Then this function return the max over all ki for all row on this processor. + */ + int MaxNumNonzeros() const {return(Graph_->MaxNumNonzeros());}; + + //! Returns the maximum number of nonzero entries across all block rows on \e all processors. + /*! This function returns the max over all processor of MaxNumNonzeros(). + */ + int GlobalMaxNumNonzeros() const {return(Graph_->GlobalMaxNumNonzeros());}; + + //! Returns the index base for row and column indices for this graph. + int IndexBase() const {return(Graph_->IndexBase());}; + + //! Returns a pointer to the Epetra_CrsGraph object associated with this matrix. + const Epetra_CrsGraph & Graph() const {return(*Graph_);}; + + //! Returns the Epetra_Import object that contains the import operations for distributed operations. + const Epetra_Import * Importer() const {return(Graph_->Importer());}; + + //! Returns the Epetra_Export object that contains the export operations for distributed operations. + const Epetra_Export * Exporter() const {return(Graph_->Exporter());}; + + //! Returns the Epetra_BlockMap object associated with the domain of this matrix operator. + const Epetra_BlockMap & DomainMap() const {return(Graph_->DomainMap());}; + + //! Returns the Epetra_BlockMap object associated with the range of this matrix operator. + const Epetra_BlockMap & RangeMap() const {return(Graph_->RangeMap());}; + + //! Returns the RowMap object as an Epetra_BlockMap (the Epetra_Map base class) needed for implementing Epetra_RowMatrix. + const Epetra_BlockMap & RowMap() const {return(Graph_->RowMap());}; + + //! Returns the ColMap as an Epetra_BlockMap (the Epetra_Map base class) needed for implementing Epetra_RowMatrix. + const Epetra_BlockMap & ColMap() const {return(Graph_->ColMap());}; + + //! Fills a matrix with rows from a source matrix based on the specified importer. + + //! Returns a pointer to the Epetra_Comm communicator associated with this matrix. + const Epetra_Comm & Comm() const {return(Graph_->Comm());}; + + //@} + + //! @name Local/Global ID methods + //@{ + //! Returns the local row index for given global row index, returns -1 if no local row for this global row. + int LRID( int GRID) const {return(Graph_->LRID(GRID));}; + + //! Returns the global row index for give local row index, returns IndexBase-1 if we don't have this local row. + int GRID( int LRID) const {return(Graph_->GRID(LRID));}; + + //! Returns the local column index for given global column index, returns -1 if no local column for this global column. + int LCID( int GCID) const {return(Graph_->LCID(GCID));}; + + //! Returns the global column index for give local column index, returns IndexBase-1 if we don't have this local column. + int GCID( int LCID) const {return(Graph_->GCID(LCID));}; + + //! Returns true if the GRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyGRID(int GRID) const {return(Graph_->MyGRID(GRID));}; + + //! Returns true if the LRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyLRID(int LRID) const {return(Graph_->MyLRID(LRID));}; + + //! Returns true if the GCID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyGCID(int GCID) const {return(Graph_->MyGCID(GCID));}; + + //! Returns true if the LRID passed in belongs to the calling processor in this map, otherwise returns false. + bool MyLCID(int LCID) const {return(Graph_->MyLCID(LCID));}; + + //! Returns true of GID is owned by the calling processor, otherwise it returns false. + bool MyGlobalBlockRow(int GID) const {return(Graph_->MyGlobalRow(GID));}; + //@} + + //! @name I/O Methods + //@{ + + //! Print method + virtual void Print(ostream & os) const; + //@} + + //! @name Additional methods required to support the Epetra_Operator interface + //@{ + + //! Returns a character string describing the operator + const char * Label() const {return(Epetra_Object::Label());}; + + //! If set true, transpose of this operator will be applied. + /*! This flag allows the transpose of the given operator to be used implicitly. Setting this flag + affects only the Apply() and ApplyInverse() methods. If the implementation of this interface + does not support transpose use, this method should return a value of -1. + + \param In + UseTranspose -If true, multiply by the transpose of operator, otherwise just use operator. + + \return Always returns 0. + */ + int SetUseTranspose(bool UseTranspose) {UseTranspose_ = UseTranspose; return(0);}; + + //! Returns the result of a Epetra_Operator applied to a Epetra_MultiVector X in Y. + /*! + \param In + X - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + int Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + //! Returns the result of a Epetra_Operator inverse applied to an Epetra_MultiVector X in Y. + /*! In this implementation, we use several existing attributes to determine how virtual + method ApplyInverse() should call the concrete method Solve(). We pass in the UpperTriangular(), + the Epetra_VbrMatrix::UseTranspose(), and NoDiagonal() methods. The most notable warning is that + if a matrix has no diagonal values we assume that there is an implicit unit diagonal that should + be accounted for when doing a triangular solve. + + \param In + X - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + int ApplyInverse(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + + //! Returns true because this class can compute an Inf-norm. + bool HasNormInf() const {return(true);}; + + //! Returns the current UseTranspose setting. + bool UseTranspose() const {return(UseTranspose_);}; + + //! Returns the Epetra_Map object associated with the domain of this matrix operator. + const Epetra_Map & OperatorDomainMap() const + { + if (!HavePointObjects_) GeneratePointObjects(); + if (UseTranspose()) return(*OperatorRangeMap_); + else return(*OperatorDomainMap_); + } + + //! Returns the Epetra_Map object associated with the range of this matrix operator. + const Epetra_Map & OperatorRangeMap() const + { + if (!HavePointObjects_) GeneratePointObjects(); + if (UseTranspose()) return(*OperatorDomainMap_); + else return(*OperatorRangeMap_); + } + + //@} + //! @name Additional methods required to implement RowMatrix interface + //@{ + + //! Returns a copy of the specified global row in user-provided arrays. + /*! + \param In + GlobalRow - Global row to extract. + \param In + Length - Length of Values and Indices. + \param Out + NumEntries - Number of nonzero entries extracted. + \param Out + Values - Extracted values for this row. + \param Out + Indices - Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. + */ + int ExtractGlobalRowCopy(int GlobalRow, int Length, int & NumEntries, double *Values, int * Indices) const; + + //! Returns a copy of the specified local row in user-provided arrays. + /*! + \param In + MyRow - Local row to extract. + \param In + Length - Length of Values and Indices. + \param Out + NumEntries - Number of nonzero entries extracted. + \param Out + Values - Extracted values for this row. + \param Out + Indices - Extracted local column indices for the corresponding values. + + \return Integer error code, set to 0 if successful. + */ + int ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, double *Values, int * Indices) const; + + //! Return the current number of values stored for the specified local row. + /*! + \param In + MyRow - Local row. + \param Out + NumEntries - Number of nonzero values. + + \return Integer error code, set to 0 if successful. + */ + int NumMyRowEntries(int MyRow, int & NumEntries) const; + + //! Returns the maximum of NumMyRowEntries() over all rows. + int MaxNumEntries() const; + + //! Returns the EpetraMap object associated with the rows of this matrix. + const Epetra_Map & RowMatrixRowMap() const + { if (!HavePointObjects_) GeneratePointObjects(); return(*RowMatrixRowMap_); }; + + //! Returns the Epetra_Map object associated with columns of this matrix. + const Epetra_Map & RowMatrixColMap() const + { if (!HavePointObjects_) GeneratePointObjects(); return(*RowMatrixColMap_); }; + + //! Returns the Epetra_Import object that contains the import operations for distributed operations. + const Epetra_Import * RowMatrixImporter() const + { if (!HavePointObjects_) GeneratePointObjects(); return(RowMatrixImporter_); }; + + //@} + + //! @name Deprecated methods: These methods still work, but will be removed in a future version + //@{ + + //! Use BlockColMap() instead. + const Epetra_BlockMap & BlockImportMap() const {return(Graph_->ImportMap());}; + + //! Use FillComplete() instead. + int TransformToLocal(); + + //! Use FillComplete(const Epetra_BlockMap& DomainMap, const Epetra_BlockMap& RangeMap) instead. + int TransformToLocal(const Epetra_BlockMap* DomainMap, const Epetra_BlockMap* RangeMap); + //@} + + protected: + void DeleteMemory(); + bool Allocated() const {return(Allocated_);}; + int SetAllocated(bool Flag) {Allocated_ = Flag; return(0);}; + Epetra_SerialDenseMatrix *** Values() const {return(Entries_);}; + + // Internal utilities + + int DoMultiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + int DoSolve(bool Upper, bool Trans, bool UnitDiagonal, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const; + void InitializeDefaults(); + int Allocate(); + int BeginInsertValues(int BlockRow, int NumBlockEntries, + int * BlockIndices, bool IndicesAreLocal); + int BeginReplaceValues(int BlockRow, int NumBlockEntries, + int *BlockIndices, bool IndicesAreLocal); + int BeginSumIntoValues(int BlockRow, int NumBlockEntries, + int *BlockIndices, bool IndicesAreLocal); + int SetupForSubmits(int BlockRow, int NumBlockEntries, int * BlockIndices, + bool IndicesAreLocal, Epetra_CombineMode SubmitMode); + int EndReplaceSumIntoValues(); + int EndInsertValues(); + + int CopyMat(double * A, int LDA, int NumRows, int NumCols, + double * B, int LDB, bool SumInto) const; + int BeginExtractBlockRowCopy(int BlockRow, int MaxNumBlockEntries, + int & RowDim, int & NumBlockEntries, + int * BlockIndices, int * ColDims, + bool IndicesAreLocal) const; + int SetupForExtracts(int BlockRow, int & RowDim, int NumBlockEntries, + bool ExtractView, bool IndicesAreLocal) const; + int ExtractBlockDimsCopy(int NumBlockEntries, int * ColDims) const; + int ExtractBlockRowPointers(int BlockRow, int MaxNumBlockEntries, + int & RowDim, int & NumBlockEntries, + int * BlockIndices, + Epetra_SerialDenseMatrix ** & Values, + bool IndicesAreLocal) const; + int BeginExtractBlockRowView(int BlockRow, int & RowDim, int & NumBlockEntries, + int * & BlockIndices, + bool IndicesAreLocal) const; + int CopyMatDiag(double * A, int LDA, int NumRows, int NumCols, + double * Diagonal) const; + int ReplaceMatDiag(double * A, int LDA, int NumRows, int NumCols, + double * Diagonal); + + //This BlockRowMultiply accepts Alpha and Beta arguments. It is called + //from within the 'solve' methods. + void BlockRowMultiply(bool TransA, int RowDim, int NumEntries, + int * BlockIndices, int RowOff, + int * FirstPointInElementList, int * ElementSizeList, + double Alpha, Epetra_SerialDenseMatrix** As, + double ** X, double Beta, double ** Y, int NumVectors) const; + + //This BlockRowMultiply doesn't accept Alpha and Beta arguments, instead it + //assumes that they are both 1.0. It is called from within the 'Multiply' + //methods. + void BlockRowMultiply(bool TransA, int RowDim, int NumEntries, + int * BlockIndices, int RowOff, + int * FirstPointInElementList, + int * ElementSizeList, + Epetra_SerialDenseMatrix** As, + double ** X, double ** Y, int NumVectors) const; + // + // Assumes Alpha=Beta=1 and works only on storage optimized matrices + // + void FastBlockRowMultiply(bool TransA, int RowDim, int NumEntries, + int * BlockIndices, int RowOff, + int * FirstPointInElementList, + int * ElementSizeList, + Epetra_SerialDenseMatrix** As, + double ** X, double ** Y, int NumVectors) const; + + int InverseSums(bool DoRows, Epetra_Vector& x) const; + int Scale(bool DoRows, const Epetra_Vector& x); + void BlockRowNormInf(int RowDim, int NumEntries, + Epetra_SerialDenseMatrix** As, + double * Y) const; + void BlockRowNormOne(int RowDim, int NumEntries, int * BlockRowIndices, + Epetra_SerialDenseMatrix** As, + int * ColFirstPointInElementList, double * x) const; + void SetStaticGraph(bool Flag) {StaticGraph_ = Flag;}; + + int CheckSizes(const Epetra_SrcDistObject& A); + + int CopyAndPermute(const Epetra_SrcDistObject & Source, + int NumSameIDs, + int NumPermuteIDs, + int * PermuteToLIDs, + int *PermuteFromLIDs, + const Epetra_OffsetIndex * Indexor); + + int PackAndPrepare(const Epetra_SrcDistObject & Source, + int NumExportIDs, + int * ExportLIDs, + int & LenExports, + char * & Exports, + int & SizeOfPacket, + int * Sizes, + bool & VarSizes, + Epetra_Distributor & Distor); + + int UnpackAndCombine(const Epetra_SrcDistObject & Source, + int NumImportIDs, + int * ImportLIDs, + int LenImports, + char * Imports, + int & SizeOfPacket, + Epetra_Distributor & Distor, + Epetra_CombineMode CombineMode, + const Epetra_OffsetIndex * Indexor); + + //! Sort column entries, row-by-row, in ascending order. + int SortEntries(); + + //! If SortEntries() has been called, this query returns true, otherwise it returns false. + bool Sorted() const {return(Graph_->Sorted());}; + + //! Add entries that have the same column index. Remove redundant entries from list. + int MergeRedundantEntries(); + + //! If MergeRedundantEntries() has been called, this query returns true, otherwise it returns false. + bool NoRedundancies() const {return(Graph_->NoRedundancies());}; + + bool StaticGraph() const {return(StaticGraph_);}; + + int GeneratePointObjects() const; + int BlockMap2PointMap(const Epetra_BlockMap & BlockMap, Epetra_Map * & PointMap) const; + int UpdateOperatorXY(const Epetra_MultiVector& X, const Epetra_MultiVector& Y) const; + + Epetra_CrsGraph * Graph_; + bool Allocated_; + bool StaticGraph_; + bool UseTranspose_; + bool constructedWithFilledGraph_; + bool matrixFillCompleteCalled_; + bool StorageOptimized_; + + int NumMyBlockRows_; + + Epetra_DataAccess CV_; + + + int * NumBlockEntriesPerRow_; + int * NumAllocatedBlockEntriesPerRow_; + int ** Indices_; + int * ElementSizeList_; + int * FirstPointInElementList_; + + Epetra_SerialDenseMatrix ***Entries_; + + double *All_Values_Orig_; + double *All_Values_; + + mutable double NormInf_; + mutable double NormOne_; + mutable double NormFrob_; + + mutable Epetra_MultiVector * ImportVector_; + mutable Epetra_MultiVector * ExportVector_; + + // State variables needed for constructing matrix entry-by-entry + mutable int *TempRowDims_; + mutable Epetra_SerialDenseMatrix **TempEntries_; + mutable int LenTemps_; + mutable int CurBlockRow_; + mutable int CurNumBlockEntries_; + mutable int * CurBlockIndices_; + mutable int CurEntry_; + mutable bool CurIndicesAreLocal_; + mutable Epetra_CombineMode CurSubmitMode_; + + // State variables needed for extracting entries + mutable int CurExtractBlockRow_; + mutable int CurExtractEntry_; + mutable int CurExtractNumBlockEntries_; + mutable bool CurExtractIndicesAreLocal_; + mutable bool CurExtractView_; + mutable int CurRowDim_; + + // State variable for extracting block diagonal entries + mutable int CurBlockDiag_; + + // Maps and importer that support the Epetra_RowMatrix interface + mutable Epetra_Map * RowMatrixRowMap_; + mutable Epetra_Map * RowMatrixColMap_; + mutable Epetra_Import * RowMatrixImporter_; + + // Maps that support the Epetra_Operator interface + mutable Epetra_Map * OperatorDomainMap_; + mutable Epetra_Map * OperatorRangeMap_; + mutable Epetra_MultiVector * OperatorX_; + mutable Epetra_MultiVector * OperatorY_; + + // bool to indicate if above four point maps and importer have already been created + mutable bool HavePointObjects_; + + bool squareFillCompleteCalled_; +}; + +#endif /* EPETRA_VBRMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_VbrRowMatrix.h b/fastlib/trilinos/include/Epetra_VbrRowMatrix.h new file mode 100644 index 0000000000..3be25171bd --- /dev/null +++ b/fastlib/trilinos/include/Epetra_VbrRowMatrix.h @@ -0,0 +1,236 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_VBRROWMATRIX_H +#define EPETRA_VBRROWMATRIX_H + +#include "Epetra_BasicRowMatrix.h" +#include "Epetra_VbrMatrix.h" +#include "Epetra_Map.h" +#include "Epetra_Comm.h" +#include "Epetra_Vector.h" +#include "Epetra_MultiVector.h" + +//! Epetra_VbrRowMatrix: A class for using an existing Epetra_VbrMatrix object as an Epetra_RowMatrix object. + +/*! The Epetra_VbrRowMatrix class takes an existing Epetra_VbrMatrix object and allows its + use as an Epetra_RowMatrix without allocating additional storage. Although the Epetra_VbrMatrix itself + inherits from Epetra_RowMatrix, a design flaw in the inheritance structure of Epetra prohibits the use of + an Epetra_VbrMatrix object as an Epetra_RowMatrix in some important situations. Therefore we recommend the + use of this class to wrap an Epetra_VbrMatrix object. + + \warning This class takes a pointer to an existing Epetra_VbrMatrix object. It is assumed that the user + will pass in a pointer to a valid Epetra_VbrMatrix object, and will retain it throughout the life of the + Epetra_VbrRowMatrix object. + +*/ + +class Epetra_VbrRowMatrix: public Epetra_BasicRowMatrix { + + public: + + //! @name Constructors/Destructor + //@{ + //! Epetra_VbrRowMatrix constuctor. + /* The constructor for this class requires a pointer to a fully constructed instance of an Epetra_VbrMatrix + object. + \param Matrix (In) Pointer to an existing Epetra_VbrMatrix. The input matrix must be retained by the user + throughout the existance of the dependent Epetra_VbrRowmatrix object. + \pre Matrix must have Matrix->Filled()==true. + */ + Epetra_VbrRowMatrix(Epetra_VbrMatrix * Matrix): Epetra_BasicRowMatrix(Matrix->Comm()), matrix_(Matrix) { + if (Matrix==0) throw Matrix->RowMatrixRowMap().ReportError("Input matrix must have called FillComplete()", -1); + SetMaps(Matrix->RowMatrixRowMap(), Matrix->RowMatrixColMap(), Matrix->OperatorDomainMap(), Matrix->OperatorRangeMap()); + if (!Matrix->Filled()) throw Matrix->RowMatrixRowMap().ReportError("Input matrix must have called FillComplete()", -1); + SetLabel("Epetra::VbrRowMatrix"); +} + + //! Epetra_VbrRowMatrix Destructor + virtual ~Epetra_VbrRowMatrix(){} + //@} + + //! @name Post-construction modifications + //@{ + //! Update the matrix to which this object points. + /* Updates the matrix that the Epetra_VbrRowMatrix will use to satisfy the Epetra_RowMatrix functionality. + \param Matrix (In) A pointer to an existing, fully constructed Epetra_VbrMatrix. + \pre Matrix must have Matrix->Filled()==true. + */ + int UpdateMatrix(Epetra_VbrMatrix * Matrix){ + if (Matrix ==0) { + EPETRA_CHK_ERR(-1); + } + else matrix_ = Matrix; + return(0); + } + //@} + + //! @name Methods required for implementing Epetra_BasicRowMatrix + //@{ + + //! Returns a copy of the specified local row in user-provided arrays. + /*! + \param MyRow (In) - Local row to extract. + \param Length (In) - Length of Values and Indices. + \param NumEntries (Out) - Number of nonzero entries extracted. + \param Values (Out) - Extracted values for this row. + \param Indices (Out) - Extracted global column indices for the corresponding values. + + \return Integer error code, set to 0 if successful, set to -1 if MyRow not valid, -2 if Length is too short (NumEntries will have required length). + */ + int ExtractMyRowCopy(int MyRow, int Length, int & NumEntries, double *Values, int * Indices) const { + + EPETRA_CHK_ERR(matrix_->ExtractMyRowCopy(MyRow, Length, NumEntries, Values, Indices)); + return(0); + } + + //! Returns a reference to the ith entry in the matrix, along with its row and column index + /*! + \param CurEntry (In) - Local entry to extract. + \param Value (Out) - Extracted reference to current values. + \param RowIndex (Out) - Row index for current entry. + \param ColIndex (Out) - Column index for current entry. + + \return Integer error code, set to 0 if successful, set to -1 if CurEntry not valid. + */ + int ExtractMyEntryView(int CurEntry, double * &Value, int & RowIndex, int & ColIndex) { + return(-1); + } + + //! Returns a const reference to the ith entry in the matrix, along with its row and column index. + /*! + \param CurEntry (In) - Local entry to extract. + \param Value (Out) - Extracted reference to current values. + \param RowIndex (Out) - Row index for current entry. + \param ColIndex (Out) - Column index for current entry. + + \return Integer error code, set to 0 if successful, set to -1 if CurEntry not valid. + */ + int ExtractMyEntryView(int CurEntry, double const * & Value, int & RowIndex, int & ColIndex) const { + return(-1); + } + + //! Return the current number of values stored for the specified local row. + /*! Similar to NumMyEntries() except NumEntries is returned as an argument + and error checking is done on the input value MyRow. + \param MyRow - (In) Local row. + \param NumEntries - (Out) Number of nonzero values. + + \return Integer error code, set to 0 if successful, set to -1 if MyRow not valid. + \pre None. + \post Unchanged. + */ + int NumMyRowEntries(int MyRow, int & NumEntries) const { + EPETRA_CHK_ERR(matrix_->NumMyRowEntries(MyRow, NumEntries)); + return(0); + } + + //@} + + //! @name Computational methods + //@{ + + //! Scales the Epetra_VbrMatrix on the right with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(j)*A(i,j) where i denotes the global row number of A + and j denotes the global column number of A. + \param In + x -The Epetra_Vector used for scaling \e this. + + \return Integer error code, set to 0 if successful. + */ + int RightScale(const Epetra_Vector& x){ + HaveNumericConstants_ = false; + UpdateFlops(NumGlobalNonzeros()); + EPETRA_CHK_ERR(matrix_->RightScale(x)); + return(0); + } + + //! Scales the Epetra_VbrMatrix on the left with a Epetra_Vector x. + /*! The \e this matrix will be scaled such that A(i,j) = x(i)*A(i,j) where i denotes the row number of A + and j denotes the column number of A. + \param In + x -A Epetra_Vector to solve for. + + \return Integer error code, set to 0 if successful. + */ + int LeftScale(const Epetra_Vector& x){ + HaveNumericConstants_ = false; + UpdateFlops(NumGlobalNonzeros()); + EPETRA_CHK_ERR(matrix_->LeftScale(x)); + return(0); + } + + //! Returns the result of a Epetra_VbrRowMatrix multiplied by a Epetra_MultiVector X in Y. + /*! + \param In + TransA -If true, multiply by the transpose of matrix, otherwise just use matrix. + \param In + X - A Epetra_MultiVector of dimension NumVectors to multiply with matrix. + \param Out + Y -A Epetra_MultiVector of dimension NumVectorscontaining result. + + \return Integer error code, set to 0 if successful. + */ + int Multiply(bool TransA, const Epetra_MultiVector& X, Epetra_MultiVector& Y) const{ + EPETRA_CHK_ERR(matrix_->Multiply(TransA, X, Y)); + return(0); + } + + //! Returns the result of a Epetra_VbrRowMatrix solve with a Epetra_MultiVector X in Y (not implemented). + /*! + \param In + Upper -If true, solve Ux = y, otherwise solve Lx = y. + \param In + Trans -If true, solve transpose problem. + \param In + UnitDiagonal -If true, assume diagonal is unit (whether it's stored or not). + \param In + X - A Epetra_MultiVector of dimension NumVectors to solve for. + \param Out + Y -A Epetra_MultiVector of dimension NumVectors containing result. + + \return Integer error code, set to 0 if successful. + */ + int Solve(bool Upper, bool Trans, bool UnitDiagonal, + const Epetra_MultiVector& X, + Epetra_MultiVector& Y) const { + EPETRA_CHK_ERR(matrix_->Solve(Upper, Trans, UnitDiagonal, X, Y)); + return(0); + } //@} + + + + private: + + Epetra_VbrMatrix * matrix_; + +}; +#endif /* EPETRA_VBRROWMATRIX_H */ diff --git a/fastlib/trilinos/include/Epetra_Vector.h b/fastlib/trilinos/include/Epetra_Vector.h new file mode 100644 index 0000000000..a20edb2df2 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Vector.h @@ -0,0 +1,450 @@ + +//@HEADER +/* +************************************************************************ + + Epetra: Linear Algebra Services Package + Copyright (2001) Sandia Corporation + +Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +license for use of this work by or on behalf of the U.S. Government. + +This library is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as +published by the Free Software Foundation; either version 2.1 of the +License, or (at your option) any later version. + +This library is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +USA +Questions? Contact Michael A. Heroux (maherou@sandia.gov) + +************************************************************************ +*/ +//@HEADER + +#ifndef EPETRA_VECTOR_H +#define EPETRA_VECTOR_H + +#include "Epetra_MultiVector.h" +class Epetra_Map; + +//! Epetra_Vector: A class for constructing and using dense vectors on a parallel computer. + +/*! The Epetra_Vector class enables the construction and use of real-valued, + double-precision dense vectors in a distributed memory environment. The distribution of the dense + vector is determined in part by a Epetra_Comm object and a Epetra_Map (or Epetra_LocalMap + or Epetra_BlockMap). + + This class is derived from the Epetra_MultiVector class. As such, it has full access + to all of the functionality provided in the Epetra_MultiVector class. + + Distributed Global vs. Replicated Local +
      +
    • Distributed Global Vectors - In most instances, a multi-vector will be partitioned + across multiple memory images associated with multiple processors. In this case, there is + a unique copy of each element and elements are spread across all processors specified by + the Epetra_Comm communicator. +
    • Replicated Local Vectors - Some algorithms use vectors that are too small to + be distributed across all processors. Replicated local vectors handle + these types of situation. +
    + +Constructing Epetra_Vectors + +There are four Epetra_Vector constructors. The first is a basic constructor that allocates +space and sets all values to zero, the second is a +copy constructor. The third and fourth constructors work with user data. These constructors have +two data access modes: +
      +
    1. Copy mode - Allocates memory and makes a copy of the user-provided data. In this case, the + user data is not needed after construction. +
    2. View mode - Creates a "view" of the user data. In this case, the + user data is required to remain intact for the life of the vector. +
    + +\warning View mode is \e extremely dangerous from a data hiding perspective. +Therefore, we strongly encourage users to develop code using Copy mode first and +only use the View mode in a secondary optimization phase. + +All Epetra_Vector constructors require a map argument that describes the layout of elements +on the parallel machine. Specifically, +\c map is a Epetra_Map, Epetra_LocalMap or Epetra_BlockMap object describing the desired +memory layout for the vector. + +There are four different Epetra_Vector constructors: +
      +
    • Basic - All values are zero. +
    • Copy - Copy an existing vector. +
    • Copy from or make view of user double array. +
    • Copy or make view of a vector from a Epetra_MultiVector object. +
    + +Extracting Data from Epetra_Vectors + +Once a Epetra_Vector is constructed, it is possible to extract a copy of the values or create +a view of them. + +\warning ExtractView functions are \e extremely dangerous from a data hiding perspective. +For both ExtractView fuctions, there is a corresponding ExtractCopy function. We +strongly encourage users to develop code using ExtractCopy functions first and +only use the ExtractView functions in a secondary optimization phase. + +There are two Extract functions: +
      +
    • ExtractCopy - Copy values into a user-provided array. +
    • ExtractView - Set user-provided array to point to Epetra_Vector data. +
    + +Vector and Utility Functions + +Once a Epetra_Vector is constructed, a variety of mathematical functions can be applied to +the vector. Specifically: +
      +
    • Dot Products. +
    • Vector Updates. +
    • \e p Norms. +
    • Weighted Norms. +
    • Minimum, Maximum and Average Values. +
    + +The final useful function is Flops(). Each Epetra_Vector object keep track of the number +of \e serial floating point operations performed using the specified object as the \e this argument +to the function. The Flops() function returns this number as a double precision number. Using this +information, in conjunction with the Epetra_Time class, one can get accurate parallel performance +numbers. + +\warning A Epetra_Map, Epetra_LocalMap or Epetra_BlockMap object is required for all + Epetra_Vector constructors. + +*/ + +//========================================================================= +class Epetra_Vector : public Epetra_MultiVector { + + public: + + //! @name Constructors/destructors + //@{ + //! Basic Epetra_Vector constuctor. + /*! Creates a Epetra_Vector object and fills with zero values. + + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + \param In + zeroOut - If true then the allocated memory will be zeroed + out initialy. If false then this memory will not + be touched which can be significantly faster. + + \warning Note that, because Epetra_LocalMap + derives from Epetra_Map and Epetra_Map derives from Epetra_BlockMap, this constructor works + for all three types of Epetra map classes. + + \return Pointer to a Epetra_Vector. + + */ + Epetra_Vector(const Epetra_BlockMap& Map, bool zeroOut = true); + + //! Epetra_Vector copy constructor. + + Epetra_Vector(const Epetra_Vector& Source); + + //! Set vector values from user array. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + \param In + V - Pointer to an array of double precision numbers.. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_Vector(Epetra_DataAccess CV, const Epetra_BlockMap& Map, double *V); + + //! Set vector values from a vector in an existing Epetra_MultiVector. + /*! + \param In + Epetra_DataAccess - Enumerated type set to Copy or View. + \param In + Map - A Epetra_LocalMap, Epetra_Map or Epetra_BlockMap. + \param In + Source - An existing fully constructed Epetra_MultiVector. + \param In + Index - Index of vector to access. + + \return Integer error code, set to 0 if successful. + + See Detailed Description section for further discussion. + */ + Epetra_Vector(Epetra_DataAccess CV, const Epetra_MultiVector& Source, int Index); + + //! Epetra_Vector destructor. + virtual ~Epetra_Vector (); + //@} + + //! @name Post-construction modification routines + //@{ + + //! Replace values in a vector with a given indexed list of values, indices are in global index space. + /*! + Replace the Indices[i] entry in the \e this object with Values[i], for i=0; iMyLength() ), -99, + "Epetra_Vector::operator[](int): " + "The index = " << index << " does not fall in the range" + "[0,"<MyLength()<<")" + ); +#endif + return Values_[index]; + } + //! Element access function. + /*! + \return V[Index]. + */ + const double& operator [] (int index) const + { +#ifdef HAVE_EPETRA_ARRAY_BOUNDS_CHECK + EPETRA_TEST_FOR_EXCEPTION( + !( 0 <= index && index < this->MyLength() ), -99, + "Epetra_Vector::operator[](int) const: " + "The index = " << index << " does not fall in the range" + "[0,"<MyLength()<<")" + ); +#endif + return Values_[index]; + } + //@} + + //! @name Expert-only unsupported methods + //@{ + + //Let the compiler know we intend to overload the base-class ResetView + //function, rather than hide it. + using Epetra_MultiVector::ResetView; + + //! Reset the view of an existing vector to point to new user data. + /*! Allows the (very) light-weight replacement of multivector values for an + existing vector that was constructed using an Epetra_DataAccess mode of View. + No checking is performed to see if the values passed in contain valid + data. It is assumed that the user has verified the integrity of data before calling + this method. This method is useful for situations where a vector is needed + for use with an Epetra operator or matrix and the user is not passing in a multivector, + or the multivector is being passed in with another map that is not exactly compatible + with the operator, but has the correct number of entries. + + This method is used by AztecOO and Ifpack in the matvec and solve methods to improve + performance and reduce repeated calls to constructors and destructors. + + @param Values Vector data. + + \return Integer error code, set to 0 if successful, -1 if the multivector was not created as a View. + + \warning This method is extremely dangerous and should only be used by experts. + */ + + int ResetView(double * Values) {EPETRA_CHK_ERR(Epetra_MultiVector::ResetView(&Values)); return(0);}; + //@} + private: + + int ChangeValues(int NumEntries, int BlockOffset, double * Values, int * Indices, bool IndicesGlobal, bool SumInto); + +}; + +#endif /* EPETRA_VECTOR_H */ diff --git a/fastlib/trilinos/include/Epetra_Version.h b/fastlib/trilinos/include/Epetra_Version.h new file mode 100644 index 0000000000..2d78a0a884 --- /dev/null +++ b/fastlib/trilinos/include/Epetra_Version.h @@ -0,0 +1,33 @@ +// @HEADER +// *********************************************************************** +// +// Epetra: Linear Algebra Services Package +// Copyright (2001) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#include "Epetra_ConfigDefs.h" + +string Epetra_Version() { + return("Epetra Version 3.6 - 08/17/2007"); +} diff --git a/fastlib/trilinos/include/Epetra_config.h b/fastlib/trilinos/include/Epetra_config.h new file mode 100644 index 0000000000..d1e2012e0f --- /dev/null +++ b/fastlib/trilinos/include/Epetra_config.h @@ -0,0 +1,151 @@ +/* src/Epetra_config.h. Generated from Epetra_config.h.in by configure. */ +/* src/Epetra_config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to dummy `main' function (if any) required to link to the Fortran + libraries. */ +/* #undef F77_DUMMY_MAIN */ + +/* Define to a macro mangling the given C identifier (in lower and upper + case), which must not contain underscores, for linking with Fortran. */ +#define F77_FUNC(name,NAME) name ## _ + +/* As F77_FUNC, but for C identifiers containing underscores. */ +#define F77_FUNC_(name,NAME) name ## __ + +/* Define if F77 and FC dummy `main' functions are identical. */ +/* #undef FC_DUMMY_MAIN_EQ_F77 */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_ASSERT_H */ + +/* Define if you have a BLAS library. */ +#define HAVE_BLAS 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CASSERT 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CMATH 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CSTDIO 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_CSTDLIB 1 + +/* Define if want to build epetra-abc */ +/* #undef HAVE_EPETRA_ARRAY_BOUNDS_CHECK */ + +/* Define if want to build epetra-examples */ +#define HAVE_EPETRA_EXAMPLES + +/* Define if want to build epetra-tests */ +#define HAVE_EPETRA_TESTS + +/* Define if want to build with epetra enabled */ +#define HAVE_EPETRA_TEUCHOS 1 + +/* Define if want to build examples */ +#define HAVE_EXAMPLES + +/* Define if you want to build export makefiles. */ +#define HAVE_EXPORT_MAKEFILES + +/* Define if want to build with fatal_messages enabled */ +#define HAVE_FATAL_MESSAGES 1 + +/* Define if want to build with format_io enabled */ +#define HAVE_FORMAT_IO 1 + +/* Define if you are using gnumake - this will shorten your link lines. */ +/* #undef HAVE_GNUMAKE */ + +/* Define to 1 if you have the header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_IOMANIP 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IOMANIP_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_IOSTREAM 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_IOSTREAM_H */ + +/* Define if you have LAPACK library. */ +#define HAVE_LAPACK 1 + +/* Define if want to build libcheck */ +#define HAVE_LIBCHECK + +/* Define to 1 if you have the header file. */ +#define HAVE_MATH_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* define if we want to use MPI */ +/* #undef HAVE_MPI */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SSTREAM 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDIO_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define if want to build tests */ +#define HAVE_TESTS + +/* Define if want to build with threads enabled */ +/* #undef HAVE_THREADS */ + +/* Define to 1 if you have the header file. */ +#define HAVE_UNISTD_H 1 + +/* Define if want to build with warning_messages enabled */ +/* #undef HAVE_WARNING_MESSAGES */ + +/* Define if want to build with zoltan enabled */ +/* #undef HAVE_ZOLTAN */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "maherou@sandia.gov" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "epetra" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "epetra 3.6" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "epetra" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "3.6" + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 diff --git a/fastlib/trilinos/include/Makefile.export.anasazi b/fastlib/trilinos/include/Makefile.export.anasazi new file mode 100644 index 0000000000..aa374f40a5 --- /dev/null +++ b/fastlib/trilinos/include/Makefile.export.anasazi @@ -0,0 +1,55 @@ +# Required dependence on epetra and teuchos +include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.epetra +include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.teuchos + +# Optional dependance on thyra for the anasazi/thyra adapters +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.thyra +#ANASAZI_THYRA_INCLUDES = -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/packages/anasazi/../../../packages/anasazi/thyra/src $(THYRA_INCLUDES) +#ANASAZI_THYRA_LIBS = $(THYRA_LIBS) + +# Optional dependencies on triutils, belos, aztecoo, and ifpack are for +# examples only. We add them ONLY to the test target. +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.triutils +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.epetraext +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.belos +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.amesos +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.aztecoo +#include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.ifpack + +_ANASAZI_INCLUDES = \ + -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include \ + -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include \ + $(TEUCHOS_INCLUDES) \ + $(EPETRA_INCLUDES) \ + $(ANASAZI_THYRA_INCLUDES) + +_ANASAZI_LIBS = $(ANASAZI_THYRA_LIBS) -L/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/lib -lanasazi $(EPETRA_LIBS) $(TEUCHOS_LIBS) -llapack -lblas -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm + +#ANASAZI_INCLUDES = $(shell perl /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/strip_dup_incl_paths.pl $(_ANASAZI_INCLUDES)) +#ANASAZI_LIBS = $(shell perl /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/strip_dup_libs.pl $(_ANASAZI_LIBS)) +ANASAZI_INCLUDES = $(_ANASAZI_INCLUDES) +ANASAZI_LIBS = $(_ANASAZI_LIBS) + +# These variables define the include path and libraries that can be used in +# the examples and tests, but that are not required to compile or link +# against the library itself. + +_ANASAZI_TEST_INCLUDES = \ + -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include \ + -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include \ + $(IFPACK_INCLUDES) \ + $(BELOS_INCLUDES) \ + $(AMESOS_INCLUDES) \ + $(AZTECOO_INCLUDE) \ + $(TRIUTILS_INCLUDES) \ + $(ANASAZI_THYRA_INCLUDES) \ + $(EPETRAEXT_INCLUDES) \ + $(EPETRA_INCLUDES) \ + $(TEUCHOS_INCLUDES) + +_ANASAZI_TEST_LIBS = $(ANASAZI_THYRA_LIBS) -L/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/lib -lanasazi $(IFPACK_LIBS) $(BELOS_LIBS) $(AMESOS_LIBS) $(AZTECOO_LIBS) $(TRIUTILS_LIBS) $(EPETRAEXT_LIBS) $(EPETRA_LIBS) $(TEUCHOS_LIBS) -llapack -lblas -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm + +#ANASAZI_TEST_INCLUDES = $(shell perl /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/strip_dup_incl_paths.pl $(_ANASAZI_TEST_INCLUDES)) +#ANASAZI_TEST_LIBS = $(shell perl /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/strip_dup_libs.pl $(_ANASAZI_TEST_LIBS)) +ANASAZI_TEST_INCLUDES = $(_ANASAZI_TEST_INCLUDES) +ANASAZI_TEST_LIBS = $(_ANASAZI_TEST_LIBS) diff --git a/fastlib/trilinos/include/Makefile.export.anasazi.macros b/fastlib/trilinos/include/Makefile.export.anasazi.macros new file mode 100644 index 0000000000..7c220c3c11 --- /dev/null +++ b/fastlib/trilinos/include/Makefile.export.anasazi.macros @@ -0,0 +1,18 @@ +ANASAZI_AR = ar +ANASAZI_CXXLD = $(ANASAZI_CXX) +ANASAZI_ALTERNATE_AR = +ANASAZI_BLAS_LIBS = -lblas +ANASAZI_CC = cc +ANASAZI_CFLAGS = -g -O2 +ANASAZI_CPPFLAGS = +ANASAZI_CXX = g++ +ANASAZI_CXXFLAGS = -g -O2 +ANASAZI_DEFS = -DHAVE_CONFIG_H +ANASAZI_F77 = f77 +ANASAZI_FFLAGS = -g -O2 +ANASAZI_FLIBS = -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm +ANASAZI_LAPACK_LIBS = -llapack +ANASAZI_LDFLAGS = +ANASAZI_LIBS = +ANASAZI_RANLIB = ranlib +ANASAZI_prefix = /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL diff --git a/fastlib/trilinos/include/Makefile.export.epetra b/fastlib/trilinos/include/Makefile.export.epetra new file mode 100644 index 0000000000..d9179a561e --- /dev/null +++ b/fastlib/trilinos/include/Makefile.export.epetra @@ -0,0 +1,15 @@ + +# Optional dependence on teuchos +include /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/Makefile.export.teuchos + +_EPETRA_INCLUDES = \ + -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include \ + -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include \ + $(TEUCHOS_INCLUDES) + +_EPETRA_LIBS = -L/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/lib -lepetra $(TEUCHOS_LIBS) -llapack -lblas -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm + +#EPETRA_INCLUDES = $(shell perl /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/strip_dup_incl_paths.pl $(_EPETRA_INCLUDES)) +#EPETRA_LIBS = $(shell perl /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include/strip_dup_libs.pl $(_EPETRA_LIBS)) +EPETRA_INCLUDES = $(_EPETRA_INCLUDES) +EPETRA_LIBS = $(_EPETRA_LIBS) diff --git a/fastlib/trilinos/include/Makefile.export.epetra.macros b/fastlib/trilinos/include/Makefile.export.epetra.macros new file mode 100644 index 0000000000..62abf687b0 --- /dev/null +++ b/fastlib/trilinos/include/Makefile.export.epetra.macros @@ -0,0 +1,18 @@ +EPETRA_AR = ar +EPETRA_CXXLD = $(EPETRA_CXX) +EPETRA_ALTERNATE_AR = +EPETRA_BLAS_LIBS = -lblas +EPETRA_CC = cc +EPETRA_CFLAGS = -g -O2 +EPETRA_CPPFLAGS = +EPETRA_CXX = g++ +EPETRA_CXXFLAGS = -g -O2 +EPETRA_DEFS = -DHAVE_CONFIG_H +EPETRA_F77 = f77 +EPETRA_FFLAGS = -g -O2 +EPETRA_FLIBS = -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm +EPETRA_LAPACK_LIBS = -llapack +EPETRA_LDFLAGS = +EPETRA_LIBS = +EPETRA_RANLIB = ranlib +EPETRA_prefix = /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL diff --git a/fastlib/trilinos/include/Makefile.export.teuchos b/fastlib/trilinos/include/Makefile.export.teuchos new file mode 100644 index 0000000000..e967e02bef --- /dev/null +++ b/fastlib/trilinos/include/Makefile.export.teuchos @@ -0,0 +1,71 @@ + +TEUCHOS_INCLUDES = -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include -I/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/include + +TEUCHOS_LIBS = -L/net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL/lib -lteuchos -llapack -lblas -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm + +############################################################################ +# +# Export MPI settings +# +############################################################################ + +# MPI libraries +TEUCHOS_MPI_LIBS = + +# MPI include path +TEUCHOS_MPI_INC = + +# Path to MPI libraries +TEUCHOS_MPI_LIBDIR = + +# Path to MPI root +TEUCHOS_MPI_DIR = + + +############################################################################ +# +# Export Fortran, BLAS, and LAPACK libraries +# +############################################################################ + +# Fortran & standard math libs +TEUCHOS_FLIBS = -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm + +# BLAS libraries +TEUCHOS_BLAS_LIBS = -lblas + +# LAPACK libraries +TEUCHOS_LAPACK_LIBS = -llapack + +# Extra libraries +TEUCHOS_EXTRA_LIBS = + +############################################################################ +# +# Export compiler settings +# +############################################################################ + +# Extra definitions +TEUCHOS_DEFS = -DHAVE_CONFIG_H + +# Fortran compilation flags +TEUCHOS_FFLAGS = -g -O2 + +# C compilation flags +TEUCHOS_CFLAGS = -g -O2 + +# C++ compilation flags +TEUCHOS_CXXFLAGS = -g -O2 + +# linker flags +TEUCHOS_LDFLAGS = + + +############################################################################ +# +# Export the ranlib and archiver to be used +# +############################################################################ + +TEUCHOS_RANLIB = ranlib diff --git a/fastlib/trilinos/include/Makefile.export.teuchos.macros b/fastlib/trilinos/include/Makefile.export.teuchos.macros new file mode 100644 index 0000000000..a765eacf58 --- /dev/null +++ b/fastlib/trilinos/include/Makefile.export.teuchos.macros @@ -0,0 +1,19 @@ +TEUCHOS_AR = ar +TEUCHOS_CXXLD = $(TEUCHOS_CXX) +TEUCHOS_ALTERNATE_AR = +TEUCHOS_BLAS_LIBS = -lblas +TEUCHOS_CC = cc +TEUCHOS_CFLAGS = -g -O2 +TEUCHOS_CPPFLAGS = +TEUCHOS_CXX = g++ +TEUCHOS_CXXFLAGS = -g -O2 +TEUCHOS_DEFS = -DHAVE_CONFIG_H +TEUCHOS_F77 = f77 +TEUCHOS_FFLAGS = -g -O2 +TEUCHOS_FLIBS = -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../lib64 -L/usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../.. -L/lib/../lib64 -L/usr/lib/../lib64 -lfrtbegin -lg2c -lm +TEUCHOS_LAPACK_LIBS = -llapack +TEUCHOS_LDFLAGS = +TEUCHOS_LIBS = +TEUCHOS_RANLIB = ranlib +TEUCHOS_prefix = /net/hu15/gtg739c/fastlib2/fastlib/bin_keep/x86_64_Linux_COMMON_gcc_COMMON/libtrilinospack_workspace/trilinos-8.0.4/LINUX_SERIAL +TEUCHOS_libteuchos_a_AR = $(AR) cru diff --git a/fastlib/trilinos/include/Teuchos_AbstractFactory.hpp b/fastlib/trilinos/include/Teuchos_AbstractFactory.hpp new file mode 100644 index 0000000000..a4e2067146 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_AbstractFactory.hpp @@ -0,0 +1,68 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_ABSTRACT_FACTORY_HPP +#define TEUCHOS_ABSTRACT_FACTORY_HPP + +#include "Teuchos_RCP.hpp" + +namespace Teuchos { + +/** \brief Simple, universal "Abstract Factory" interface for the + * dynamic creation of objects. + * + * While RCP provides for specialized deallocation + * policies it does not abstract, in any way, how an object is first + * allocated. The most general way to abstract how an object is + * allocated is to use an "Abstract Factory". This base class defines + * the most basic "Abstract Factory" interface and defines only one + * virtual function, create() that returns a + * RCP-wrapped object. + */ +template +class AbstractFactory { +public: + +#ifndef DOXYGEN_COMPILE + /** \brief . */ + typedef Teuchos::RCP obj_ptr_t; +#endif + + /** \brief . */ + virtual ~AbstractFactory() {} + + /** \brief Create an object of type T returned as a smart reference + * counting pointer object. + */ + virtual obj_ptr_t create() const = 0; + +}; // class AbstractFactory + +} // end Teuchos + +#endif // TEUCHOS_ABSTRACT_FACTORY_HPP diff --git a/fastlib/trilinos/include/Teuchos_AbstractFactoryStd.hpp b/fastlib/trilinos/include/Teuchos_AbstractFactoryStd.hpp new file mode 100644 index 0000000000..1d20e6b0d4 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_AbstractFactoryStd.hpp @@ -0,0 +1,205 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_ABSTRACT_FACTORY_STD_HPP +#define TEUCHOS_ABSTRACT_FACTORY_STD_HPP + +#include "Teuchos_AbstractFactory.hpp" + +namespace Teuchos { + +/** \brief Default post-modification policy class for + * AbstractFactorStd which does nothing! + */ +template +class PostModNothing { +public: + /** \brief . */ + void initialize(T_impl* p) const {} // required! +}; + +/** \brief Default allocation policy class for + * AbstractFactoryStd which returns new T_impl(). + */ +template +class AllocatorNew { +public: + /** \brief . */ + typedef Teuchos::RCP ptr_t; // required! + /** \brief . */ + const ptr_t allocate() const { return Teuchos::rcp(new T_impl()); } // required! +}; + +/** \brief Simple, templated concrete subclass of universal "Abstract + * Factory" interface for the creation of objects. + * + * This concrete subclass represents a general + * AbstractFactory subclass that can be modified through + * policy template parameters. This class is templated on the + * interface type T_itfc that is exposed by the + * AbstractFactory base interface and by a (concrete) + * implementation type T_impl. The most typical use of this + * subclass is to use a concrete, default-constructable subclass for + * T_impl and then to simply instantiate a concrete abstract + * factory for that class using: + + \verbatim + + Teuchos::AbstractFactoryStd abstractFactory; + \endverbatim + * + * For this default usage, The only requirements for the derived classes type + * T_impl is that it allow the default constructor + * T_impl::T_impl() (i.e. dont make T_impl::T_impl() + * private) and that it allow T_impl::new() and + * T_impl::delete (i.e. don't make them private functions, see + * Meyers, More Effective C++, Item 27). + + * However, this subclass is also templated on two other policy types that + * allow a modification on how objects are created and destroyed. The first + * templated policy type, T_PostMod, defines how an object is + * modified after it is initially created. The second templated policy type, + * T_Allocator, defines exactly how an object is created (and + * therefore also how it is destroyed). These type two policy classes are + * described in more detail below. + * + * The type T_PostMod is responsible for performing any post + * modifications on a dynamically allocated object before returning it from + * create(). The requirements for the type T_PostMod are + * that it has a default constructor, a copy constructor and a method + * T_PostMod::initialize(T_itfc2*) const that will perform any + * required post modifications (initializations). The type T_itfc2 + * argument for this function must be a base class of T_impl of + * course. The default type for T_PostMod is + * PostModNothing which does nothing. + * + * The type T_Allocator allows for specialized memory allocation and + * cleanup. This type must allow the default constructor and copy constructor + * and have a method Teuchos::RCP T_Allocator::allocate() + * const which creates a smart reference-counted pointer to the allocated + * object. Also, in returning a RCP<> object, the client can + * set a deallocatioin policy object that can specialize the deallocation of + * the object (see RCP). In defining a specialized + * T_Allocator class, the client can all initialize the object using + * more than just the default constructor. Therefore, if the client provides + * a specialized T_Allocator class, there are no restrictions on the + * class T_impl (i.e. does not have to have a default constructor or + * allow new or delete). The default class for + * T_Allocator is AllocatorNew who's + * allocate() function just returns rcp(new T_impl()). + * + * Since the T_Allocator class can specialize both the memory + * management and can initialize the object using more that the default + * constructor, the class T_PostMod may seem unecessary. However, it + * is more likely that the client will want to define an initialization for a + * set of classes through an abstract interface and can not for a particular + * concrete subclass. Also the initialization for an object can be orthogonal + * to how it is created and destroyed, thus the two classes T_PostMod + * and T_Allocator are both needed for a more general implementation. + */ +template + ,class T_Allocator = AllocatorNew + > +class AbstractFactoryStd : public AbstractFactory { +public: + + typedef typename Teuchos::AbstractFactory::obj_ptr_t obj_ptr_t; // RAB: 20030916: G++ 3.2 complains without this + + /** \brief . */ + AbstractFactoryStd( const T_PostMod& post_mod = T_PostMod(), const T_Allocator& alloc = T_Allocator() ); + + /** @name Overriden from AbstractFactory */ + //@{ + /** \brief . */ + obj_ptr_t create() const; + //@} + +private: + T_PostMod post_mod_; + T_Allocator alloc_; + +}; + + +/** \brief Nonmember constructor for an standar abstract factory object. + * + * \relates AbstractFactoryStd + */ +template +RCP > +abstractFactoryStd() +{ + return rcp( + new AbstractFactoryStd,AllocatorNew >() + ); +} + + +/** \brief Nonmember constructor for an standar abstract factory object. + * + * \relates AbstractFactoryStd + */ +template +RCP > +abstractFactoryStd( const T_Allocator& alloc = T_Allocator() ) +{ + return rcp( + new AbstractFactoryStd,T_Allocator>( + PostModNothing(), alloc + ) + ); +} + + +// /////////////////////////////////////////////////////// +// Template member definitions + +template +inline +AbstractFactoryStd::AbstractFactoryStd( + const T_PostMod& post_mod, const T_Allocator& alloc + ) + :post_mod_(post_mod) + ,alloc_(alloc) +{} + +template +inline +typename AbstractFactoryStd::obj_ptr_t +AbstractFactoryStd::create() const +{ + typename T_Allocator::ptr_t + ptr = alloc_.allocate(); + post_mod_.initialize(ptr.get()); + return ptr; +} + +} // end Teuchos + +#endif // TEUCHOS_ABSTRACT_FACTORY_STD_HPP diff --git a/fastlib/trilinos/include/Teuchos_Array.hpp b/fastlib/trilinos/include/Teuchos_Array.hpp new file mode 100644 index 0000000000..a9624d4666 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Array.hpp @@ -0,0 +1,491 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_ARRAY_H +#define TEUCHOS_ARRAY_H + +/*! \file Teuchos_Array.hpp + \brief Templated array class derived from the STL std::vector +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_TestForException.hpp" +#include "Teuchos_Utils.hpp" +#include "Teuchos_TypeNameTraits.hpp" + +namespace Teuchos +{ + + /** \brief . + * \relates Array + */ + class InvalidArrayStringRepresentation : public std::logic_error + {public:InvalidArrayStringRepresentation(const std::string& what_arg) : std::logic_error(what_arg) {}}; + + /** + * \brief Array is a templated array class derived from the STL std::vector, but with + * index boundschecking and an extended interface. + */ + template + class Array : public std::vector + { + public: + //! Empty constructor + Array(); + + //! Allocate an array with n elements + Array(int n); + + //! Allocate n elements, and fill with value \c t + Array(int n, const T& t); + + //! Add a new entry at the end of the array. Resize to allow space for the new entry. + inline Array& append(const T& entry) {this->push_back(entry); return *this;} + + //! Remove the i-th element from the array, with optional boundschecking. + void remove(int i); + + /*! \brief Return number of elements in the array. + * Equivalent to size(), but included for backwards compatibility. + */ + int length() const {return this->size();} + + //! Read/Write access to a the i-th element, with optional boundschecking. + inline T& operator[](int i); + + //! Read-only access to a the i-th element, with optional boundschecking. + inline const T& operator[](int i) const; + + //! Write Array as a std::string + std::string toString() const ; + + //! Return true if Array has been compiled with boundschecking on + static bool hasBoundsChecking(); + + private: + + /** check for a bounds violation if HAVE_ARRAY_BOUNDSCHECK has been + * defined as 1. */ + void indexCheckCrash(int i) const; + }; + + /** \relates Array + \brief Write an Array to a stream + */ + template std::ostream& operator<<(std::ostream& os, + const Array& array); + + /** \relates Array */ + template int hashCode(const Array& array); + + /** \relates Array */ + template std::string toString(const Array& array); + + template inline Array::Array() + : std::vector() + {} + + template inline Array::Array(int n) + : std::vector(n) + {} + + template inline Array::Array(int n, const T& t) + : std::vector(n, t) + {} + + template + void Array::remove(int i) { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + indexCheckCrash(i); +#endif + // Erase the i-th element of this array. + this->erase( this->begin() + i ); + } + + template inline + T& Array::operator[](int i) { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + indexCheckCrash(i); +#endif + return std::vector::operator[](i); + } + + template inline + const T& Array::operator[](int i) const { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + indexCheckCrash(i); +#endif + return std::vector::operator[](i); + } + + template inline + bool Array::hasBoundsChecking() + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + return true; +#else + return false; +#endif + } + + template inline + void Array::indexCheckCrash(int i) const + { + TEST_FOR_EXCEPTION( + !( 0 <= i && i < length() ), std::range_error, + "Array<"<::name()<<">::indexCheckCrash: " + "index " << i << " out of range [0, "<< length() << ")" + ); + } + + // print in form (), (1), or (1,2) + template inline std::ostream& operator<<(std::ostream& os, const Array& array) + { + return os << Teuchos::toString(array); + } + + template inline int hashCode(const Array& array) + { + int rtn = hashCode(array.length()); + for (int i=0; i inline std::string Array::toString() const + { + std::ostringstream ss; + ss << "{"; + + for (int i=0; i inline + std::string toString(const Array& array) + { + return array.toString(); + } + + /** \brief Converts from std::string representation (as created by + * toString()) back into the array object. + * + * \param arrayStr + * [in] The std::string representation of the array (see below). + * + * Exceptions: If the std::string representation is not valid, then an + * std::exception of type InvalidArrayStringRepresentation with be + * thrown with a decent error message attached. + * + * The formating of the std::string arrayStr must look like: + + \verbatim + + { val[0], val[1], val[2], val[3], ..., val[n-1] } + + \endverbatim + + * Currently operator>>() is used to convert the entries from their + * std::string representation to objects of type T. White space is + * unimportant and the parser keys off of ',', '{' and '}' so even newlines + * are allowed. In the future, a traits class might be defined that will + * allow for finer-grained control of how the conversion from strings to + * values is performed in cases where operator>>() does not exist + * for certain types. + * + * Warning! Currently this function only supports reading in flat + * array objects for basic types like bool, int, and + * double and does not yet support nested arrays (i.e. no + * Array >) or other such fancy nested types. Support + * for nested arrays and other user defined types T can be added in + * the future with no impact on user code. Only the parser for the array + * needs to be improved. More specifically, the current implementation will + * not work for any types T who's std::string representation contains + * the characters ',' or '}'. This implementation can be + * modified to allow any such types by watching for the nesting of common + * enclosing structures like [...], {...} or + * (...) within each entry of the std::string representation. However, + * this should all just work fine on most machines for the types + * int, bool, float, double etc. + * + * Warning! Trying to read in an array in std::string format of doubles in + * scientific notation such as {1e+2,3.53+6,...} into an array + * object such as Array will not yield the correct results. + * If one wants to allow a neutral std::string representation to be read in as an + * Array object or an Array object, then + * general formating such as {100,3530000,...} should be used. + * This templated function is unable to deal std::complex type conversion issues. + * + * \relates Array. + */ + template + Array fromStringToArray(const std::string& arrayStr) + { + const std::string str = Utils::trimWhiteSpace(arrayStr); + std::istringstream iss(str); + TEST_FOR_EXCEPTION( + ( str[0]!='{' || str[str.length()-1] != '}' ) + ,InvalidArrayStringRepresentation + ,"Error, the std::string:\n" + "----------\n" + < a; + while( !iss.eof() ) { + // Get the basic entry std::string + std::string entryStr; + std::getline(iss,entryStr,','); // Get next entry up to ,! + // ToDo: Above, we might have to be careful to look for the opening and + // closing of parentheses in order not to pick up an internal ',' in the + // middle of an entry (for a std::complex number for instance). The above + // implementation assumes that there will be no commas in the middle of + // the std::string representation of an entry. This is certainly true for + // the types bool, int, float, and double. + // + // Trim whitespace from beginning and end + entryStr = Utils::trimWhiteSpace(entryStr); + // Remove the final '}' if this is the last entry and we did not + // actually terminate the above getline(...) on ',' + bool found_end = false; + if(entryStr[entryStr.length()-1]=='}') { + entryStr = entryStr.substr(0,entryStr.length()-1); + found_end = true; + if( entryStr.length()==0 && a.size()==0 ) + return a; // This is the empty array "{}" (with any spaces in it!) + } + TEST_FOR_EXCEPTION( + 0 == entryStr.length() + ,InvalidArrayStringRepresentation + ,"Error, the std::string:\n" + "----------\n" + <> entry; // Assumes type has operator>>(...) defined! + // ToDo: We may need to define a traits class to allow us to specialized + // how conversion from a std::string to a object is done! + a.push_back(entry); + // At the end of the loop body here, if we have reached the last '}' + // then the input stream iss should be empty and iss.eof() should be + // true, so the loop should terminate. We put an std::exception test here + // just in case something has gone wrong. + TEST_FOR_EXCEPTION( + found_end && !iss.eof() + ,InvalidArrayStringRepresentation + ,"Error, the std::string:\n" + "----------\n" + < inline + Array tuple(const T& a) + { + Array rtn(1, a); + return rtn; + } + + /** \relates Array + \brief Create an array with two entries + */ + template inline + Array tuple(const T& a, const T& b) + { + Array rtn(2); + rtn[0] = a; + rtn[1] = b; + return rtn; + } + + /** \relates Array + \brief Create an array with three entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c) + { + Array rtn(3); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + return rtn; + } + + /** \relates Array + \brief Create an array with four entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d) + { + Array rtn(4); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + return rtn; + } + + /** \relates Array + \brief Create an array with five entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d, const T& e) + { + Array rtn(5); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + rtn[4] = e; + return rtn; + } + + + /** \relates Array + \brief Create an array with six entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d, const T& e, + const T& f) + { + Array rtn(6); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + rtn[4] = e; + rtn[5] = f; + return rtn; + } + + /** \relates Array + \brief Create an array with seven entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d, const T& e, + const T& f, const T& g) + { + Array rtn(7); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + rtn[4] = e; + rtn[5] = f; + rtn[6] = g; + return rtn; + } + + /** \relates Array + \brief Create an array with eight entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d, const T& e, + const T& f, const T& g, const T& h) + { + Array rtn(8); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + rtn[4] = e; + rtn[5] = f; + rtn[6] = g; + rtn[7] = h; + return rtn; + } + + /** \relates Array + \brief Create an array with nine entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d, const T& e, + const T& f, const T& g, const T& h, const T& i) + { + Array rtn(9); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + rtn[4] = e; + rtn[5] = f; + rtn[6] = g; + rtn[7] = h; + rtn[8] = i; + return rtn; + } + + + /** \relates Array + \brief Create an array with ten entries + */ + template inline + Array tuple(const T& a, const T& b, const T& c, const T& d, const T& e, + const T& f, const T& g, const T& h, const T& i, const T& j) + { + Array rtn(10); + rtn[0] = a; + rtn[1] = b; + rtn[2] = c; + rtn[3] = d; + rtn[4] = e; + rtn[5] = f; + rtn[6] = g; + rtn[7] = h; + rtn[8] = i; + rtn[9] = j; + return rtn; + } +} + +#endif // TEUCHOS_ARRAY_H diff --git a/fastlib/trilinos/include/Teuchos_ArrayRCP.hpp b/fastlib/trilinos/include/Teuchos_ArrayRCP.hpp new file mode 100644 index 0000000000..768895847d --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ArrayRCP.hpp @@ -0,0 +1,746 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_ARRAY_RCP_HPP +#define TEUCHOS_ARRAY_RCP_HPP + +#include "Teuchos_ArrayRCPDecl.hpp" +#include "Teuchos_TestForException.hpp" +#include "Teuchos_dyn_cast.hpp" +#include "Teuchos_map.hpp" + +namespace Teuchos { + +// Constructors/Initializers + +template +inline +ArrayRCP::ArrayRCP( ENull ) + : ptr_(NULL) + , node_(NULL) + , lowerOffset_(0) + , upperOffset_(-1) +{} + +template +REFCOUNTPTR_INLINE +ArrayRCP::ArrayRCP(const ArrayRCP& r_ptr) + : ptr_(r_ptr.ptr_), node_(r_ptr.node_) + , lowerOffset_(r_ptr.lowerOffset_) + , upperOffset_(r_ptr.upperOffset_) +{ + if(node_) node_->incr_count(); +} + +template +REFCOUNTPTR_INLINE +ArrayRCP::~ArrayRCP() +{ + if(node_ && node_->deincr_count() == 0 ) { +#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES + printActiveRCPNodes.foo(); // Make sure this object is used! + remove_RCP_node(node_); +#endif + delete node_; + } +} + +template +REFCOUNTPTR_INLINE +ArrayRCP& ArrayRCP::operator=(const ArrayRCP& r_ptr) +{ + if( this == &r_ptr ) + return *this; // Assignment to self + if( node_ && !node_->deincr_count() ) { +#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES + remove_RCP_node(node_); +#endif + delete node_; + } + ptr_ = r_ptr.ptr_; + node_ = r_ptr.node_; + lowerOffset_ = r_ptr.lowerOffset_; + upperOffset_ = r_ptr.upperOffset_; + if(node_) node_->incr_count(); + return *this; +} + +// Object/Pointer Access Functions + +template +inline +T* ArrayRCP::operator->() const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + assert_in_range(0,1); +#endif + return ptr_; +} + +template +inline +T& ArrayRCP::operator*() const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + assert_in_range(0,1); +#endif + return *ptr_; +} + +template +inline +T* ArrayRCP::get() const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + if(ptr_) { + assert_in_range(0,1); + } +#endif + return ptr_; +} + +template +REFCOUNTPTR_INLINE +T& ArrayRCP::operator[](Ordinal offset) const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + assert_in_range(offset,1); +#endif + return ptr_[offset]; +} + +// Pointer Arithmetic Functions + +template +REFCOUNTPTR_INLINE +ArrayRCP& ArrayRCP::operator++() +{ + if(ptr_) { + ++ptr_; + --lowerOffset_; + --upperOffset_; + } + return *this; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP ArrayRCP::operator++(int) +{ + ArrayRCP r_ptr = *this; + ++(*this); + return r_ptr; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP& ArrayRCP::operator--() +{ + if(ptr_) { + --ptr_; + ++lowerOffset_; + ++upperOffset_; + } + return *this; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP ArrayRCP::operator--(int) +{ + ArrayRCP r_ptr = *this; + --(*this); + return r_ptr; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP& ArrayRCP::operator+=(Ordinal offset) +{ + if(ptr_) { + ptr_ += offset; + lowerOffset_ -= offset; + upperOffset_ -= offset; + } + return *this; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP& ArrayRCP::operator-=(Ordinal offset) +{ + if(ptr_) { + ptr_ -= offset; + lowerOffset_ += offset; + upperOffset_ += offset; + } + return *this; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP ArrayRCP::operator+(Ordinal offset) const +{ + ArrayRCP r_ptr = *this; + r_ptr+=(offset); + return r_ptr; +} + +template +REFCOUNTPTR_INLINE +ArrayRCP ArrayRCP::operator-(Ordinal offset) const +{ + ArrayRCP r_ptr = *this; + r_ptr-=offset; + return r_ptr; +} + +// Views + +template +REFCOUNTPTR_INLINE +ArrayRCP ArrayRCP::getConst() const +{ + const T *cptr = ptr_; // Will not compile if not legal! + return ArrayRCP(cptr,lowerOffset_,upperOffset_,node_); +} + +template +REFCOUNTPTR_INLINE +ArrayRCP +ArrayRCP::subview( Ordinal lowerOffset, Ordinal size ) const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + assert_in_range(lowerOffset,size); +#endif + ArrayRCP ptr = *this; + ptr.ptr_ = ptr.ptr_ + lowerOffset; + ptr.lowerOffset_ = 0; + ptr.upperOffset_ = size-1; + return ptr; +} + +// General query functions + +template +REFCOUNTPTR_INLINE +int ArrayRCP::count() const { + if(node_) + return node_->count(); + return 0; +} + +template +REFCOUNTPTR_INLINE +template +bool ArrayRCP::shares_resource(const ArrayRCP& r_ptr) const +{ + return node_ == r_ptr.access_node(); + // Note: above, r_ptr is *not* the same class type as *this so we can not + // access its node_ member directly! This is an interesting detail to the + // C++ protected/private protection mechanism! +} + +template +REFCOUNTPTR_INLINE +typename ArrayRCP::Ordinal +ArrayRCP::lowerOffset() const +{ + return lowerOffset_; +} + +template +REFCOUNTPTR_INLINE +typename ArrayRCP::Ordinal +ArrayRCP::upperOffset() const +{ + return upperOffset_; +} + +template +REFCOUNTPTR_INLINE +typename ArrayRCP::Ordinal +ArrayRCP::size() const +{ + return upperOffset_-lowerOffset_+1; +} + +// Standard Container-Like Functions + +template +REFCOUNTPTR_INLINE +typename ArrayRCP::const_iterator ArrayRCP::begin() const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + return *this; +#else + return ptr_; +#endif +} + +template +REFCOUNTPTR_INLINE +typename ArrayRCP::const_iterator +ArrayRCP::end() const +{ +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + return *this + (upperOffset_ + 1); +#else + return ptr_ + (upperOffset_ + 1); +#endif +} + +// Ownership + +template +REFCOUNTPTR_INLINE +T* ArrayRCP::release() +{ + if(node_) + node_->has_ownership(false); + return ptr_; +} + +template +REFCOUNTPTR_INLINE +void ArrayRCP::set_has_ownership() +{ + if(node_) + node_->has_ownership(true); +} + +template +REFCOUNTPTR_INLINE +bool ArrayRCP::has_ownership() const +{ + if(node_) + return node_->has_ownership(); + return false; +} + +// Assertion Functions. + +template +inline +const ArrayRCP& +ArrayRCP::assert_not_null() const +{ + if(!ptr_) PrivateUtilityPack::throw_null(TypeNameTraits::name()); + return *this; +} + +template +inline +const ArrayRCP& +ArrayRCP::assert_in_range( Ordinal lowerOffset, Ordinal size ) const +{ + assert_not_null(); + TEST_FOR_EXCEPTION( + !( lowerOffset_ <= lowerOffset && lowerOffset+size-1 <= upperOffset_ ), std::logic_error + ,"Teuchos::ArrayRCP<"<::name()<<">::assert_in_range:" + " Error, [lowerOffset,lowerOffset+size-1] = ["< +inline +ArrayRCP::ArrayRCP( + T* p, Ordinal lowerOffset, Ordinal upperOffset, bool has_ownership + ) + : ptr_(p) + , node_( + p + ? new PrivateUtilityPack::RCP_node_tmpl >( + p,DeallocArrayDelete(),has_ownership + ) + : NULL + ) + ,lowerOffset_(lowerOffset) + ,upperOffset_(upperOffset) +{ +#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES + if(node_) { + std::ostringstream os; + os << "{T=\'"<::name()<<"\',Concrete T=\'"< +REFCOUNTPTR_INLINE +template +ArrayRCP::ArrayRCP( + T* p, Ordinal lowerOffset, Ordinal upperOffset, Dealloc_T dealloc, bool has_ownership + ) + : ptr_(p) + , node_( p ? new PrivateUtilityPack::RCP_node_tmpl(p,dealloc,has_ownership) : NULL ) + ,lowerOffset_(lowerOffset) + ,upperOffset_(upperOffset) +{ +#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES + if(node_) { + std::ostringstream os; + os << "{T=\'"<::name()<<"\',Concrete T=\'"< +inline +ArrayRCP::ArrayRCP( + T* p, Ordinal lowerOffset, Ordinal upperOffset, node_t* node + ) + : ptr_(p) + , node_(node) + ,lowerOffset_(lowerOffset) + ,upperOffset_(upperOffset) +{ + if(node_) node_->incr_count(); +} + +template +inline +T*& ArrayRCP::access_ptr() +{ return ptr_; } + +template +inline +T* ArrayRCP::access_ptr() const +{ return ptr_; } + +template +inline +typename ArrayRCP::node_t*& ArrayRCP::access_node() +{ return node_; } + +template +inline +typename ArrayRCP::node_t* ArrayRCP::access_node() const +{ return node_; } + +} // end namespace Teuchos + +// /////////////////////////////////////////// +// Non-member functions for ArrayRCP + +namespace Teuchos { +namespace Utilities { +template +inline void assert_shares_resource( + const ArrayRCP &p1, const ArrayRCP &p2 + ) +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT(!p1.shares_resource(p2)); +#endif +} +} // namespace Utilities +} // namespace Teuchos + +template +inline +Teuchos::ArrayRCP +Teuchos::arcp( +T* p, typename ArrayRCP::Ordinal lowerOffset + ,typename ArrayRCP::Ordinal size + ,bool owns_mem + ) +{ + return ArrayRCP(p,lowerOffset,lowerOffset+size-1,owns_mem); +} + +template +inline +Teuchos::ArrayRCP +Teuchos::arcp( +T* p, typename ArrayRCP::Ordinal lowerOffset + ,typename ArrayRCP::Ordinal size + ,Dealloc_T dealloc, bool owns_mem + ) +{ + return ArrayRCP(p,lowerOffset,lowerOffset+size-1,dealloc,owns_mem); +} + +template +inline +Teuchos::ArrayRCP +Teuchos::arcp( typename ArrayRCP::Ordinal size ) +{ + return ArrayRCP(new T[size],0,size-1,true); +} + +template +REFCOUNTPTR_INLINE +Teuchos::ArrayRCP +Teuchos::arcp( const RCP > &v ) +{ + Teuchos::ArrayRCP ptr = arcp(&(*v)[0],0,v->size(),false); + set_extra_data( v, "std::vector", &ptr ); + return ptr; +} + +template +REFCOUNTPTR_INLINE +Teuchos::RCP > +Teuchos::get_std_vector( const ArrayRCP &ptr ) +{ + return get_extra_data > >(ptr,"std::vector"); +} + +template +REFCOUNTPTR_INLINE +Teuchos::ArrayRCP +Teuchos::arcp( const RCP > &v ) +{ + Teuchos::ArrayRCP ptr = arcp(&(*v)[0],0,v->size(),false); + set_extra_data( v, "std::vector", &ptr ); + return ptr; +} + +template +REFCOUNTPTR_INLINE +Teuchos::RCP > +Teuchos::get_std_vector( const ArrayRCP &ptr ) +{ + return get_extra_data > >(ptr,"std::vector"); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::is_null( const ArrayRCP &p ) +{ + return p.access_ptr() == NULL; +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator==( const ArrayRCP &p, ENull ) +{ + return p.access_ptr() == NULL; +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator!=( const ArrayRCP &p, ENull ) +{ + return p.access_ptr() != NULL; +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator==( const ArrayRCP &p1, const ArrayRCP &p2 ) +{ + return p1.access_ptr() == p2.access_ptr(); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator!=( const ArrayRCP &p1, const ArrayRCP &p2 ) +{ + return p1.access_ptr() != p2.access_ptr(); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator<( const ArrayRCP &p1, const ArrayRCP &p2 ) +{ + return p1.access_ptr() < p2.access_ptr(); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator<=( const ArrayRCP &p1, const ArrayRCP &p2 ) +{ + Utilities::assert_shares_resource(p1,p2); + return p1.access_ptr() <= p2.access_ptr(); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator>( const ArrayRCP &p1, const ArrayRCP &p2 ) +{ + Utilities::assert_shares_resource(p1,p2); + return p1.access_ptr() > p2.access_ptr(); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator>=( const ArrayRCP &p1, const ArrayRCP &p2 ) +{ + Utilities::assert_shares_resource(p1,p2); + return p1.access_ptr() >= p2.access_ptr(); +} + +template +REFCOUNTPTR_INLINE +Teuchos::ArrayRCP +Teuchos::arcp_reinterpret_cast(const ArrayRCP& p1) +{ + typedef typename ArrayRCP::Ordinal Ordinal; + const int sizeOfT2ToT1 = sizeof(T2)/sizeof(T1); + Ordinal lowerOffset2 = p1.lowerOffset() / sizeOfT2ToT1; + Ordinal upperOffset2 = (p1.upperOffset()+1) / sizeOfT2ToT1 -1; + T2 *ptr2 = reinterpret_cast(p1.get()); + return ArrayRCP( + ptr2,lowerOffset2,upperOffset2 + ,p1.access_node() + ); + // Note: Above is just fine even if p1.get()==NULL! +} + +template +REFCOUNTPTR_INLINE +Teuchos::ArrayRCP +Teuchos::arcp_implicit_cast(const ArrayRCP& p1) +{ + typedef typename ArrayRCP::Ordinal Ordinal; + T2 * raw_ptr2 = p1.get(); + return ArrayRCP( + raw_ptr2,p1.lowerOffset(),p1.upperOffset() + ,p1.access_node() + ); + // Note: Above is just fine even if p1.get()==NULL! +} + +template +REFCOUNTPTR_INLINE +void Teuchos::set_extra_data( + const T1 &extra_data, const std::string& name, Teuchos::ArrayRCP *p + ,EPrePostDestruction destroy_when, bool force_unique + ) +{ + p->assert_not_null(); + p->access_node()->set_extra_data( any(extra_data), name, destroy_when, force_unique ); +} + +template +REFCOUNTPTR_INLINE +T1& Teuchos::get_extra_data( ArrayRCP& p, const std::string& name ) +{ + p.assert_not_null(); + return any_cast(p.access_node()->get_extra_data(TypeNameTraits::name(),name)); +} + +template +REFCOUNTPTR_INLINE +const T1& Teuchos::get_extra_data( const ArrayRCP& p, const std::string& name ) +{ + p.assert_not_null(); + return any_cast(p.access_node()->get_extra_data(TypeNameTraits::name(),name)); +} + +template +REFCOUNTPTR_INLINE +T1* Teuchos::get_optional_extra_data( ArrayRCP& p, const std::string& name ) +{ + p.assert_not_null(); + any *extra_data = p.access_node()->get_optional_extra_data(TypeNameTraits::name(),name); + if( extra_data ) return &any_cast(*extra_data); + return NULL; +} + +template +REFCOUNTPTR_INLINE +const T1* Teuchos::get_optional_extra_data( const ArrayRCP& p, const std::string& name ) +{ + p.assert_not_null(); + any *extra_data = p.access_node()->get_optional_extra_data(TypeNameTraits::name(),name); + if( extra_data ) return &any_cast(*extra_data); + return NULL; +} + +template +REFCOUNTPTR_INLINE +Dealloc_T& +Teuchos::get_dealloc( ArrayRCP& p ) +{ + typedef PrivateUtilityPack::RCP_node_tmpl requested_type; + p.assert_not_null(); + PrivateUtilityPack::RCP_node_tmpl + *dnode = dynamic_cast*>(p.access_node()); + TEST_FOR_EXCEPTION( + dnode==NULL, std::logic_error + ,"get_dealloc<" << TypeNameTraits::name() << "," << TypeNameTraits::name() << ">(p): " + << "Error, requested type \'" << TypeNameTraits::name() + << "\' does not match actual type of the node \'" << typeName(*p.access_node()) << "!" + ); + return dnode->get_dealloc(); +} + +template +inline +const Dealloc_T& +Teuchos::get_dealloc( const Teuchos::ArrayRCP& p ) +{ + return get_dealloc(const_cast&>(p)); +} + +template +REFCOUNTPTR_INLINE +Dealloc_T* +Teuchos::get_optional_dealloc( ArrayRCP& p ) +{ + p.assert_not_null(); + typedef PrivateUtilityPack::RCP_node_tmpl + RCPNT; + RCPNT *dnode = dynamic_cast(p.access_node()); + if(dnode) + return &dnode->get_dealloc(); + return NULL; +} + +template +inline +const Dealloc_T* +Teuchos::get_optional_dealloc( const Teuchos::ArrayRCP& p ) +{ + return get_optional_dealloc(const_cast&>(p)); +} + +template +std::ostream& Teuchos::operator<<( std::ostream& out, const ArrayRCP& p ) +{ + out + << TypeNameTraits >::name() << "{" + << "ptr="<<(const void*)(p.get()) // I can't find any alternative to this C cast :-( + <<",lowerOffset="<RCP except + * that it is designed to use reference counting to manage an array of objects + * that use value semantics. Managing an array of objects is very different + * from managing a pointer to an individual, possibly polymorphic, object. For + * example, while implicit conversions from derived to base types is a good + * thing when dealing with pointers to single objects, it is a very bad thing + * when working with arrays of objects. Therefore, this class contains those + * capabilities of raw pointers that are good dealing with arrays of objects + * but excludes those that are bad, such as implicit conversions from derived + * to base types. + * + * Note that all access will be checked at runtime to avoid reading invalid + * memory if HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined which it is if + * --enable-teuchos-abc is given to the configure script. + * In order to be able to check access, every %ArrayRCP must + * be constructed given a range. When HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + * is defined, this class simply does not give up a raw pointer or raw + * reference to any internally referenced object if that object does not fall + * with the range of valid data. + * + * ToDo: Finish documentation! + * + * \ingroup teuchos_mem_mng_grp + */ +template +class ArrayRCP { +public: + + //! @name Public types + //@{ + + /** \brief . */ + typedef T element_type; + /** \brief. */ + typedef Teuchos_Index Ordinal; +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + /** \brief . */ + typedef ArrayRCP iterator; +#else + typedef T* iterator; +#endif +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK +/** \brief . */ + typedef ArrayRCP const_iterator; +#else + typedef T* const_iterator; +#endif + + //@} + + //! @name Constructors/Initializers + //@{ + + /** \brief Initialize ArrayRCP to NULL. + * + * This allows clients to write code like: + \code + ArrayRCP p = null; + \endcode + * or + \code + ArrayRCP p; + \endcode + * and construct to NULL + */ + ArrayRCP( ENull null_arg = null ); + + /** \brief Initialize from another ArrayRCP object. + * + * After construction, this and r_ptr will + * reference the same array. + * + * This form of the copy constructor is required even though the + * below more general templated version is sufficient since some + * compilers will generate this function automatically which will + * give an incorrect implementation. + * + * Postconditions:
      + *
    • this->get() == r_ptr.get() + *
    • this->count() == r_ptr.count() + *
    • this->has_ownership() == r_ptr.has_ownership() + *
    • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 + *
    + */ + ArrayRCP(const ArrayRCP& r_ptr); + + /** \brief Removes a reference to a dynamically allocated array and possibly deletes + * the array if owned. + * + * Deallocates array if this->has_ownership() == true and + * this->count() == 1. If this->count() == 1 but + * this->has_ownership() == false then the array is not deleted + * (usually using delete []). If this->count() > 1 then + * the internal reference count shared by all the other related + * ArrayRCP<...> objects for this shared array is + * deincremented by one. If this->get() == NULL then nothing + * happens. + */ + ~ArrayRCP(); + + /** \brief Copy the pointer to the referenced array and increment the + * reference count. + * + * If this->has_ownership() == true and this->count() == 1 + * before this operation is called, then the array will be deleted prior to + * binding to the pointer (possibly NULL) pointed to in + * r_ptr. Assignment to self (i.e. this->get() == + * r_ptr.get()) is harmless and this function does nothing. + * + * Postconditions: + *
      + *
    • this->get() == r_ptr.get() + *
    • this->count() == r_ptr.count() + *
    • this->has_ownership() == r_ptr.has_ownership() + *
    • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 + *
    + */ + ArrayRCP& operator=(const ArrayRCP& r_ptr); + + //@} + + //! @name Object/Pointer Access Functions + //@{ + + /** \brief Pointer (->) access to members of underlying object for + * current position. + * + * Preconditions:
      + *
    • this->get() != NULL + *
    • this->lowerOffset() <= 0 + *
    • this->upperOffset() >= 0 + *
    + */ + T* operator->() const; + + /** \brief Dereference the underlying object for the current pointer + * position. + * + * Preconditions:
      + *
    • this->get() != NULL + *
    • this->lowerOffset() <= 0 + *
    • this->upperOffset() >= 0 + *
    + */ + T& operator*() const; + + /** \brief Get the raw C++ pointer to the underlying object. + * + * Preconditions:
      + *
    • [*this != null] this->lowerOffset() <= 0 + *
    • [*this != null] this->upperOffset() >= 0 + *
    + */ + T* get() const; + + /** \brief Random object access. + * + * Preconditions:
      + *
    • this->get() != NULL + *
    • this->lowerOffset() <= offset && offset <= this->upperOffset() + *
    + */ + T& operator[](Ordinal offset) const; + + //@} + + //! @name Pointer Arithmetic Functions + //@{ + + /** \brief Prefix increment of pointer (i.e. ++ptr). + * + * Does nothing if this->get() == NULL. + * + * Postconditions:
      + *
    • [this->get()!=NULL] this->get() is incremented by 1 + *
    • [this->get()!=NULL] this->lowerOffset() is deincremented by 1 + *
    • [this->get()!=NULL] this->upperOffset() is deincremented by 1 + *
    + */ + ArrayRCP& operator++(); + + /** \brief Postfix increment of pointer (i.e. ptr++). + * + * Does nothing if this->get() == NULL. + * + * Postconditions:
      + *
    • this->get() is incremented by 1 + *
    • this->lowerOffset() is deincremented by 1 + *
    • this->upperOffset() is deincremented by 1 + *
    + */ + ArrayRCP operator++(int); + + /** \brief Prefix deincrement of pointer (i.e. --ptr). + * + * Does nothing if this->get() == NULL. + * + * Postconditions:
      + *
    • [this->get()!=NULL] this->get() is deincremented by 1 + *
    • [this->get()!=NULL] this->lowerOffset() is incremented by 1 + *
    • [this->get()!=NULL] this->upperOffset() is incremented by 1 + *
    + */ + ArrayRCP& operator--(); + + /** \brief Postfix deincrement of pointer (i.e. ptr--). + * + * Does nothing if this->get() == NULL. + * + * Postconditions:
      + *
    • this->get() is dincremented by 1 + *
    • this->lowerOffset() is incremented by 1 + *
    • this->upperOffset() is incremented by 1 + *
    + */ + ArrayRCP operator--(int); + + /** \brief Pointer integer increment (i.e. ptr+=offset). + * + * Does nothing if this->get() == NULL. + * + * Postconditions:
      + *
    • [this->get()!=NULL] this->get() is incremented by offset + *
    • [this->get()!=NULL] this->lowerOffset() is deincremented by offset + *
    • [this->get()!=NULL] this->upperOffset() is deincremented by offset + *
    + */ + ArrayRCP& operator+=(Ordinal offset); + + /** \brief Pointer integer increment (i.e. ptr-=offset). + * + * Does nothing if this->get() == NULL. + * + * Postconditions:
      + *
    • [this->get()!=NULL] this->get() is deincremented by offset + *
    • [this->get()!=NULL] this->lowerOffset() is incremented by offset + *
    • [this->get()!=NULL] this->upperOffset() is incremented by offset + *
    + */ + ArrayRCP& operator-=(Ordinal offset); + + /** \brief Pointer integer increment (i.e. ptr+offset). + * + * Returns a null pointer if this->get() == NULL. + * + * Postconditions:
      + *
    • [this->get()!=NULL] return->get() == this->get() + offset + *
    • [this->get()!=NULL] return->lowerOffset() == this->lowerOffset() - offset + *
    • [this->get()!=NULL] return->upperOffset() == this->upperOffset() - offset + *
    + * + * Note that since implicit conversion of ArrayRCP + * objects is not allowed that it does not help at all to make this function + * into a non-member function. + */ + ArrayRCP operator+(Ordinal offset) const; + + /** \brief Pointer integer deincrement (i.e. ptr-offset). + * + * Returns a null pointer if this->get() == NULL. + * + * Postconditions:
      + *
    • [this->get()!=NULL] return->get() == this->get() - offset + *
    • [this->get()!=NULL] return->lowerOffset() == this->lowerOffset() + offset + *
    • [this->get()!=NULL] return->upperOffset() == this->upperOffset() + offset + *
    + * + * Note that since implicit conversion of ArrayRCP + * objects is not allowed that it does not help at all to make this function + * into a non-member function. + */ + ArrayRCP operator-(Ordinal offset) const; + + //@} + + //! @name Views + //@{ + + /** \brief Return object for only const access to data. + * + * This function should only compile successfully if the type T is + * not already declared const! + */ + ArrayRCP getConst() const; + + /** \brief Return a view of a contiguous range of elements. + * + * Preconditions:
      + *
    • this->get() != NULL + *
    • this->lowerOffset() <= lowerOffset + *
    • lowerOffset + size - 1 <= this->upperOffset() + *
    + * + * Postconditions:
      + *
    • return->get() == this->get() + lowerOffset + *
    • return->lowerOffset() == 0 + *
    • return->upperOffset() == size-1 + *
    + */ + ArrayRCP subview( Ordinal lowerOffset, Ordinal size ) const; + + //@} + + //! @name General query functions + //@{ + + /** \brief Return the number of ArrayRCP<> objects that have a reference + * to the underlying pointer that is being shared. + * + * @return If this->get() == NULL then this function returns 0. + * Otherwise, this function returns > 0. + */ + int count() const; + + /** \brief Returns true if the smart pointers share the same underlying reference-counted object. + * + * This method does more than just check if this->get() == r_ptr.get(). + * It also checks to see if the underlying reference counting machinery is the + * same. + */ + template + bool shares_resource(const ArrayRCP& r_ptr) const; + + /** \brief Return the lower offset to valid data. */ + Ordinal lowerOffset() const; + + /** \brief Return the upper offset to valid data. */ + Ordinal upperOffset() const; + + /** \brief The total number of items in the managed array + * (i.e. upperOffset()-lowerOffset()+1). + */ + Ordinal size() const; + + //@} + + //! @name Standard Container-Like Functions + //@{ + + /** \brief Return an iterator to beginning of the array of data. + * + * If HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined then the iterator + * returned is an ArrayRCP object and all operations are + * checked at runtime. When HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is not + * defined, the a raw pointer T* is returned for fast execution. + * + * Postconditions:
      + *
    • [this->get()!=NULL] &*return == this->get() + *
    • [this->get()==NULL] return == (null or NULL) + *
    + */ + const_iterator begin() const; + + /** \brief Return an iterator to past the end of the array of data. + * + * If HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is defined then the iterator + * returned is an ArrayRCP object and all operations are + * checked at runtime. When HAVE_TEUCHOS_ARRAY_BOUNDSCHECK is not + * defined, the a raw pointer T* is returned for fast execution. + * + * Postconditions:
      + *
    • [this->get()!=NULL] &*end == this->get()+(this->upperOffset()+1) + *
    • [this->get()==NULL] return == (null or NULL) + *
    + */ + const_iterator end() const; + + //@} + + //! @name Ownership + //@{ + + /** \brief Release the ownership of the underlying array. + * + * After this function is called then the client is responsible for deleting + * the returned pointer no matter how many ref_count_ptr objects + * have a reference to it. If this->get() == NULL, then + * this call is meaningless. + * + * Note that this function does not have the exact same semantics as does + * auto_ptr::release(). In auto_ptr::release(), + * this is set to NULL while here in ArrayRCP:: + * release() only an ownership flag is set and this still points to + * the same array. It would be difficult to duplicate the behavior of + * auto_ptr::release() for this class. + * + * Postconditions:
      + *
    • this->has_ownership() == false + *
    + * + * @return Returns the value of this->get() + */ + T* release(); + + /** \brief Give this and other ArrayRCP<> objects + * ownership of the underlying referenced array to delete it. + * + * See ~ArrayRCP() above. This function does nothing if + * this->get() == NULL. + * + * Postconditions:
      + *
    • If this->get() == NULL then + *
        + *
      • this->has_ownership() == false (always!). + *
      + *
    • else + *
        + *
      • this->has_ownership() == true + *
      + *
    + */ + void set_has_ownership(); + + /** \brief Returns true if this has ownership of object pointed to + * by this->get() in order to delete it. + * + * See ~ArrayRCP() above. + * + * \return If this->get() == NULL then this function always returns + * false. Otherwise the value returned from this function depends + * on which function was called most recently, if any; + * set_has_ownership() (true) or release() + * (false). + */ + bool has_ownership() const; + + //@} + + //! @name Assertion Functions. + //@{ + + /** \brief Throws std::logic_error if this->get()==NULL, + * otherwise returns reference to *this. + */ + const ArrayRCP& assert_not_null() const; + + /** \brief Throws std::logic_error if this->get()==NULL + * orthis->get()!=NULL && (lowerOffset < this->lowerOffset() || + * this->upperOffset() < upperOffset, otherwise returns reference to + * *this + */ + const ArrayRCP& assert_in_range( Ordinal lowerOffset, Ordinal size ) const; + + //@} + +public: // Bad bad bad + + // ////////////////////////////////////// + // Private types + + typedef PrivateUtilityPack::RCP_node node_t; + +private: + + // ////////////////////////////////////////////////////////////// + // Private data members + + T *ptr_; // NULL if this pointer is null + node_t *node_; // NULL if this pointer is null + Ordinal lowerOffset_; + Ordinal upperOffset_; + +public: +#ifndef DOXYGEN_COMPILE + // These constructors should be private but I have not had good luck making + // this portable (i.e. using friendship etc.) in the past + ArrayRCP( T* p, Ordinal lowerOffset, Ordinal upperOffset, bool has_ownership ); + template + ArrayRCP( T* p, Ordinal lowerOffset, Ordinal upperOffset, Dealloc_T dealloc, bool has_ownership ); + // This is a very bad breach of encapsulation that is needed since MS VC++ 5.0 will + // not allow me to declare template functions as friends. + ArrayRCP( T* p, Ordinal lowerOffset, Ordinal upperOffset, node_t* node); + T*& access_ptr(); + T* access_ptr() const; // No preconditions + node_t*& access_node(); + node_t* access_node() const; +#endif + +}; // end class ArrayRCP<...> + +/** \brief Traits specialization. + * + * \relates ArrayRCP + */ +template +class TypeNameTraits > { +public: + static std::string name() { return "ArrayRCP<"+TypeNameTraits::name()+">"; } +}; + +/** \brief Wraps a preallocated array of data with the assumption to call the + * array version of delete. + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp( + T* p, typename ArrayRCP::Ordinal lowerOffset + ,typename ArrayRCP::Ordinal size + , bool owns_mem = true + ); + +/** \brief Wraps a preallocated array of data and uses a templated + * deallocation strategy object to define deletion . + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp( + T* p, typename ArrayRCP::Ordinal lowerOffset + ,typename ArrayRCP::Ordinal size + , Dealloc_T dealloc, bool owns_mem + ); + +/** \brief Allocate a new array just given a dimension. + * + * Warning! The memory is allocated using new T[size] and is + * *not* initialized (unless there is a default constructor for a user-defined + * type). + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp( typename ArrayRCP::Ordinal size ); + +/** \brief Wrap an std::vector object as an + * ArrayRCP object. + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp( const RCP > &v ); + +/** \brief Wrap a const std::vector object as an + * ArrayRCP object. + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp( const RCP > &v ); + +/** \brief Get an std::vector object out of an + * ArrayRCP object that was created using the + * arcp() above to wrap the std::vector in the first place.. + * + * \relates ArrayRCP + */ +template +RCP > get_std_vector( const ArrayRCP &ptr ); + +/** \brief Get a const std::vector object out of an + * ArrayRCP object that was created using the + * arcp() above to wrap the std::vector in the first place. + * + * \relates ArrayRCP + */ +template +RCP > get_std_vector( const ArrayRCP &ptr ); + +/** \brief Returns true if p.get()==NULL. + * + * \relates ArrayRCP + */ +template +bool is_null( const ArrayRCP &p ); + +/** \brief Returns true if p.get()==NULL. + * + * \relates ArrayRCP + */ +template +bool operator==( const ArrayRCP &p, ENull ); + +/** \brief Returns true if p.get()!=NULL. + * + * \relates ArrayRCP + */ +template +bool operator!=( const ArrayRCP &p, ENull ); + +/** \brief . + * + * \relates ArrayRCP + */ +template +bool operator==( const ArrayRCP &p1, const ArrayRCP &p2 ); + +/** \brief . + * + * \relates ArrayRCP + */ +template +bool operator!=( const ArrayRCP &p1, const ArrayRCP &p2 ); + +/** \brief . + * + * \relates ArrayRCP + */ +template +bool operator<( const ArrayRCP &p1, const ArrayRCP &p2 ); + +/** \brief . + * + * \relates ArrayRCP + */ +template +bool operator<=( const ArrayRCP &p1, const ArrayRCP &p2 ); + +/** \brief . + * + * \relates ArrayRCP + */ +template +bool operator>( const ArrayRCP &p1, const ArrayRCP &p2 ); + +/** \brief . + * + * \relates ArrayRCP + */ +template +bool operator>=( const ArrayRCP &p1, const ArrayRCP &p2 ); + +/** \brief Reinterpret cast of underlying ArrayRCP type from + * T1* to T2*. + * + * The function will compile only if (reinterpret_cast(p1.get());) compiles. + * + * Warning! Do not use this function unless you absolutely know what + * you are doing. Doing a reinterpret cast is always a tricking thing and + * must only be done by developers who are 100% comfortable with what they are + * doing. + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp_reinterpret_cast(const ArrayRCP& p1); + +/** \brief Implicit case the underlying ArrayRCP type from + * T1* to T2*. + * + * The function will compile only if (T2 *p = p1.get();) compiles. + * + * Warning! Do not use this function unless you absolutely know what you + * are doing. While implicit casting of pointers to single objects is usually + * 100% safe, implicit casting pointers to arrays of objects can be very + * dangerous. One std::exception that is always safe is when you are implicit + * casting an array of pointers to non-const objects to an array of const + * pointers to const objects. For example, the following implicit conversion + * from a array pointer objects aptr1 of type + * ArrayRCP to + + \code + + ArrayRCP + aptr2 = arcp_implicit_cast(ptr1); + + \endcode + + * is always legal and safe to do. + * + * \relates ArrayRCP + */ +template +ArrayRCP arcp_implicit_cast(const ArrayRCP& p1); + +/** \brief Set extra data associated with a ArrayRCP object. + * + * @param extra_data + * [in] Data object that will be set (copied) + * @param name [in] The name given to the extra data. The value of + * name together with the data type T1 of the + * extra data must be unique from any other such data or + * the other data will be overwritten. + * @param p [out] On output, will be updated with the input extra_data + * @param destroy_when + * [in] Determines when extra_data will be destroyed + * in relation to the underlying reference-counted object. + * If destroy_when==PRE_DESTROY then extra_data + * will be deleted before the underlying reference-counted object. + * If destroy_when==POST_DESTROY (the default) then extra_data + * will be deleted after the underlying reference-counted object. + * @param force_unique + * [in] Determines if this type and name pair must be unique + * in which case if an object with this same type and name + * already exists, then an std::exception will be thrown. + * The default is true for safety. + * + * If there is a call to this function with the same type of extra + * data T1 and same arguments p and name + * has already been made, then the current piece of extra data already + * set will be overwritten with extra_data. However, if the + * type of the extra data T1 is different, then the extra + * data can be added and not overwrite existing extra data. This + * means that extra data is keyed on both the type and name. This + * helps to minimize the chance that clients will unexpectedly + * overwrite data by accident. + * + * When the last RefcountPtr object is removed and the + * reference-count node is deleted, then objects are deleted in the following + * order: (1) All of the extra data that where added with + * destroy_when==PRE_DESTROY are first, (2) then the underlying + * reference-counted object is deleted, and (3) the rest of the extra data + * that was added with destroy_when==PRE_DESTROY is then deleted. + * The order in which the objects are destroyed is not guaranteed. Therefore, + * clients should be careful not to add extra data that has deletion + * dependencies (instead consider using nested ArrayRCP objects as extra + * data which will guarantee the order of deletion). + * + * Preconditions:
      + *
    • p->get() != NULL (throws std::logic_error) + *
    • If this function has already been called with the same template + * type T1 for extra_data and the same std::string name + * and force_unique==true, then an std::invalid_argument + * std::exception will be thrown. + *
    + * + * Note, this function is made a non-member function to be consistent + * with the non-member get_extra_data() functions. + * + * \relates ArrayRCP + */ +template +void set_extra_data( const T1 &extra_data, const std::string& name, ArrayRCP *p + ,EPrePostDestruction destroy_when +#ifndef __sun + = POST_DESTROY +#endif + ,bool force_unique +#ifndef __sun + = true +#endif + ); +#ifdef __sun +template +inline void set_extra_data( const T1 &extra_data, const std::string& name, ArrayRCP *p ) +{ set_extra_data( extra_data, name, p, POST_DESTROY, true ); } +template +inline void set_extra_data( const T1 &extra_data, const std::string& name, ArrayRCP *p, EPrePostDestruction destroy_when ) +{ set_extra_data( extra_data, name, p, destroy_when, true ); } +#endif + +/** \brief Get a non-const reference to extra data associated with a ArrayRCP object. + * + * @param p [in] Smart pointer object that extra data is being extracted from. + * @param name [in] Name of the extra data. + * + * @return Returns a non-const reference to the extra_data object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • name and T1 must have been used in a previous + * call to set_extra_data() (throws std::invalid_argument). + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * \relates ArrayRCP + */ +template +T1& get_extra_data( ArrayRCP& p, const std::string& name ); + +/** \brief Get a const reference to extra data associated with a ArrayRCP object. + * + * @param p [in] Smart pointer object that extra data is being extracted from. + * @param name [in] Name of the extra data. + * + * @return Returns a const reference to the extra_data object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • name and T1 must have been used in a previous + * call to set_extra_data() (throws std::invalid_argument). + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * Also note that this const version is a false sense of security + * since a client can always copy a const ArrayRCP object + * into a non-const object and then use the non-const version to + * change the data. However, its presence will help to avoid some + * types of accidental changes to this extra data. + * + * \relates ArrayRCP + */ +template +const T1& get_extra_data( const ArrayRCP& p, const std::string& name ); + +/** \brief Get a pointer to non-const extra data (if it exists) associated + * with a ArrayRCP object. + * + * @param p [in] Smart pointer object that extra data is being extracted from. + * @param name [in] Name of the extra data. + * + * @return Returns a non-const pointer to the extra_data object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If name and T1 have been used in a previous + * call to set_extra_data() then return !=NULL + * and otherwise return == NULL. + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * \relates ArrayRCP + */ +template +T1* get_optional_extra_data( ArrayRCP& p, const std::string& name ); + +/** \brief Get a pointer to const extra data (if it exists) associated with a ArrayRCP object. + * + * @param p [in] Smart pointer object that extra data is being extracted from. + * @param name [in] Name of the extra data. + * + * @return Returns a const pointer to the extra_data object if it exists. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If name and T1 have been used in a previous + * call to set_extra_data() then return !=NULL + * and otherwise return == NULL. + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * Also note that this const version is a false sense of security + * since a client can always copy a const ArrayRCP object + * into a non-const object and then use the non-const version to + * change the data. However, its presence will help to avoid some + * types of accidental changes to this extra data. + * + * \relates ArrayRCP + */ +template +const T1* get_optional_extra_data( const ArrayRCP& p, const std::string& name ); + +/** \brief Return a non-const reference to the underlying deallocator object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • The deallocator object type used to construct p is same as Dealloc_T + * (throws std::logic_error) + *
    + * + * \relates ArrayRCP + */ +template +Dealloc_T& get_dealloc( ArrayRCP& p ); + +/** \brief Return a const reference to the underlying deallocator object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • The deallocator object type used to construct p is same as Dealloc_T + * (throws std::logic_error) + *
    + * + * Note that the const version of this function provides only + * a very ineffective attempt to avoid accidental changes to the + * deallocation object. A client can always just create a new + * non-const ArrayRCP object from any + * const ArrayRCP object and then call the + * non-const version of this function. + * + * \relates ArrayRCP + */ +template +const Dealloc_T& get_dealloc( const ArrayRCP& p ); + +/** \brief Return a pointer to the underlying non-const deallocator + * object if it exists. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If the deallocator object type used to construct p is same as Dealloc_T + * then return!=NULL, otherwise return==NULL + *
    + * + * \relates ArrayRCP + */ +template +Dealloc_T* get_optional_dealloc( ArrayRCP& p ); + +/** \brief Return a pointer to the underlying const deallocator + * object if it exists. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If the deallocator object type used to construct p is same as Dealloc_T + * then return!=NULL, otherwise return==NULL + *
    + * + * Note that the const version of this function provides only + * a very ineffective attempt to avoid accidental changes to the + * deallocation object. A client can always just create a new + * non-const ArrayRCP object from any + * const ArrayRCP object and then call the + * non-const version of this function. + * + * \relates ArrayRCP + */ +template +const Dealloc_T* get_optional_dealloc( const ArrayRCP& p ); + +/** \brief Output stream inserter. + * + * The implementation of this function just print pointer addresses and + * therefore puts not restrictions on the data types involved. + * + * \relates ArrayRCP + */ +template +std::ostream& operator<<( std::ostream& out, const ArrayRCP& p ); + +} // end namespace Teuchos + +#endif // TEUCHOS_ARRAY_RCP_DECL_HPP diff --git a/fastlib/trilinos/include/Teuchos_Assert.hpp b/fastlib/trilinos/include/Teuchos_Assert.hpp new file mode 100644 index 0000000000..7096e06392 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Assert.hpp @@ -0,0 +1,77 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_ASSERT_HPP +#define TEUCHOS_ASSERT_HPP + + +#include "Teuchos_TestForException.hpp" + + +/** \brief This macro is throws when an assert fails. + * + * \note The std::exception thrown is std::logic_error. + * + * \ingroup TestForException_grp + */ +#define TEUCHOS_ASSERT(assertion_test) TEST_FOR_EXCEPT(!(assertion_test)) + + +/** \brief This macro asserts that an integral number fallis in the range + * [lower_inclusive,upper_exclusive) + * + * \note The std::exception thrown is std::logic_error. + * + * \ingroup TestForException_grp + */ +#define TEUCHOS_ASSERT_IN_RANGE_UPPER_EXCLUSIVE( index, lower_inclusive, upper_exclusive ) \ + { \ + TEST_FOR_EXCEPTION( \ + !( (lower_inclusive) <= (index) && (index) < (upper_exclusive) ), \ + std::out_of_range, \ + "Error, the index " #index " = " << (index) << " does not fall in the range" \ + "["<<(lower_inclusive)<<","<<(upper_exclusive)<<")!" ); \ + } + + +/** \brief This macro is checks that to numbers are equal and if not then + * throws an exception with a good error message. + * + * \note The std::exception thrown is std::logic_error. + * + * \ingroup TestForException_grp + */ +#define TEUCHOS_ASSERT_EQUALITY( val1, val2 ) \ + { \ + TEST_FOR_EXCEPTION( \ + (val1) != (val2), std::out_of_range, \ + "Error, (" #val1 " = " << (val1) << ") != (" #val2 " = " << (val2) << ")!" ); \ + } + + +#endif // TEUCHOS_ASSERT_HPP diff --git a/fastlib/trilinos/include/Teuchos_BLAS.hpp b/fastlib/trilinos/include/Teuchos_BLAS.hpp new file mode 100644 index 0000000000..0eed17b13f --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_BLAS.hpp @@ -0,0 +1,1867 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 06.16.03 -- Start over from scratch +// 06.16.03 -- Initial templatization (Tpetra_BLAS.cpp is no longer needed) +// 06.18.03 -- Changed xxxxx_() function calls to XXXXX_F77() +// -- Added warning messages for generic calls +// 07.08.03 -- Move into Teuchos package/namespace +// 07.24.03 -- The first iteration of BLAS generics is nearing completion. Caveats: +// * TRSM isn't finished yet; it works for one case at the moment (left side, upper tri., no transpose, no unit diag.) +// * Many of the generic implementations are quite inefficient, ugly, or both. I wrote these to be easy to debug, not for efficiency or legibility. The next iteration will improve both of these aspects as much as possible. +// * Very little verification of input parameters is done, save for the character-type arguments (TRANS, etc.) which is quite robust. +// * All of the routines that make use of both an incx and incy parameter (which includes much of the L1 BLAS) are set up to work iff incx == incy && incx > 0. Allowing for differing/negative values of incx/incy should be relatively trivial. +// * All of the L2/L3 routines assume that the entire matrix is being used (that is, if A is mxn, lda = m); they don't work on submatrices yet. This *should* be a reasonably trivial thing to fix, as well. +// -- Removed warning messages for generic calls +// 08.08.03 -- TRSM now works for all cases where SIDE == L and DIAG == N. DIAG == U is implemented but does not work correctly; SIDE == R is not yet implemented. +// 08.14.03 -- TRSM now works for all cases and accepts (and uses) leading-dimension information. +// 09.26.03 -- character input replaced with enumerated input to cause compiling errors and not run-time errors ( suggested by RAB ). + +#ifndef _TEUCHOS_BLAS_HPP_ +#define _TEUCHOS_BLAS_HPP_ + +/*! \file Teuchos_BLAS.hpp + \brief Templated interface class to BLAS routines. +*/ +/** \example BLAS/cxx_main.cpp + This is an example of how to use the Teuchos::BLAS class. +*/ + +/* for INTEL_CXML, the second arg may need to be changed to 'one'. If so +the appropriate declaration of one will need to be added back into +functions that include the macro: +*/ +#if defined (INTEL_CXML) + unsigned int one=1; +#endif + +#ifdef CHAR_MACRO +#undef CHAR_MACRO +#endif +#if defined (INTEL_CXML) +#define CHAR_MACRO(char_var) &char_var, one +#else +#define CHAR_MACRO(char_var) &char_var +#endif + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_BLAS_wrappers.hpp" +#include "Teuchos_BLAS_types.hpp" +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_OrdinalTraits.hpp" + +/*! \class Teuchos::BLAS + \brief The Templated BLAS Wrapper Class. + + The Teuchos::BLAS class provides functionality similar to the BLAS + (Basic Linear Algebra Subprograms). The BLAS provide portable, high- + performance implementations of kernels such as dense std::vector multiplication, + dot products, dense matrix-std::vector multiplication and dense matrix-matrix + multiplication. + + The standard BLAS interface is Fortran-specific. Unfortunately, the + interface between C++ and Fortran is not standard across all computer + platforms. The Teuchos_BLAS class provides C++ bindings for the BLAS + kernels in order to insulate the rest of Petra from the details of + C++ to Fortran translation. + + In addition to giving access the standard BLAS functionality. + Teuchos::BLAS also provide functionality for any class that + defines the +, - * and / operators. + + Teuchos::BLAS is a single memory image interface only. This is appropriate + since the standard BLAS are only specified for serial execution + (or shared memory parallel). + + \note +
      +
    1. These templates are specialized to use the Fortran BLAS routines for + scalar types \c float and \c double. + +
    2. If Teuchos is configured with \c --enable-teuchos-std::complex then these templates + are specialized for scalar types \c std::complex and \c std::complex also. +
    +*/ + +namespace Teuchos +{ + extern const char ESideChar[]; + extern const char ETranspChar[]; + extern const char EUploChar[]; + extern const char EDiagChar[]; + + template + class BLAS + { + + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + + public: + //! @name Constructor/Destructor. + //@{ + + //! Default constructor. + inline BLAS(void) {} + + //! Copy constructor. + inline BLAS(const BLAS& BLAS_source) {} + + //! Destructor. + inline virtual ~BLAS(void) {} + //@} + + //! @name Level 1 BLAS Routines. + //@{ + + //! Computes a Givens plane rotation. + void ROTG(ScalarType* da, ScalarType* db, MagnitudeType* c, ScalarType* s) const; + + //! Applies a Givens plane rotation. + void ROT(const OrdinalType n, ScalarType* dx, const OrdinalType incx, ScalarType* dy, const OrdinalType incy, MagnitudeType* c, ScalarType* s) const; + + //! Scale the std::vector \c x by the constant \c alpha. + void SCAL(const OrdinalType n, const ScalarType alpha, ScalarType* x, const OrdinalType incx) const; + + //! Copy the std::vector \c x to the std::vector \c y. + void COPY(const OrdinalType n, const ScalarType* x, const OrdinalType incx, ScalarType* y, const OrdinalType incy) const; + + //! Perform the operation: \c y \c <- \c y+alpha*x. + void AXPY(const OrdinalType n, const ScalarType alpha, const ScalarType* x, const OrdinalType incx, ScalarType* y, const OrdinalType incy) const; + + //! Sum the absolute values of the entries of \c x. + typename ScalarTraits::magnitudeType ASUM(const OrdinalType n, const ScalarType* x, const OrdinalType incx) const; + + //! Form the dot product of the vectors \c x and \c y. + ScalarType DOT(const OrdinalType n, const ScalarType* x, const OrdinalType incx, const ScalarType* y, const OrdinalType incy) const; + + //! Compute the 2-norm of the std::vector \c x. + typename ScalarTraits::magnitudeType NRM2(const OrdinalType n, const ScalarType* x, const OrdinalType incx) const; + + //! Return the index of the element of \c x with the maximum magnitude. + OrdinalType IAMAX(const OrdinalType n, const ScalarType* x, const OrdinalType incx) const; + + //@} + + //! @name Level 2 BLAS Routines. + //@{ + + //! Performs the matrix-std::vector operation: \c y \c <- \c alpha*A*x+beta*y or \c y \c <- \c alpha*A'*x+beta*y where \c A is a general \c m by \c n matrix. + void GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* A, + const OrdinalType lda, const ScalarType* x, const OrdinalType incx, const ScalarType beta, ScalarType* y, const OrdinalType incy) const; + + //! Performs the matrix-std::vector operation: \c x \c <- \c A*x or \c x \c <- \c A'*x where \c A is a unit/non-unit \c n by \c n upper/lower triangular matrix. + void TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const ScalarType* A, + const OrdinalType lda, ScalarType* x, const OrdinalType incx) const; + + //! Performs the rank 1 operation: \c A \c <- \c alpha*x*y'+A. + void GER(const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* x, const OrdinalType incx, + const ScalarType* y, const OrdinalType incy, ScalarType* A, const OrdinalType lda) const; + //@} + + //! @name Level 3 BLAS Routines. + //@{ + + //! Performs the matrix-matrix operation: \c C \c <- \c alpha*op(A)*op(B)+beta*C where \c op(A) is either \c A or \c A', \c op(B) is either \c B or \c B', and C is an \c m by \c k matrix. + void GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, const ScalarType* B, const OrdinalType ldb, const ScalarType beta, ScalarType* C, const OrdinalType ldc) const; + + //! Performs the matrix-matrix operation: \c C \c <- \c alpha*A*B+beta*C or \c C \c <- \c alpha*B*A+beta*C where \c A is an \c m by \c m or \c n by \c n symmetric matrix and \c B is a general matrix. + void SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, const ScalarType* B, const OrdinalType ldb, const ScalarType beta, ScalarType* C, const OrdinalType ldc) const; + + //! Performs the matrix-matrix operation: \c C \c <- \c alpha*op(A)*B+beta*C or \c C \c <- \c alpha*B*op(A)+beta*C where \c op(A) is an unit/non-unit, upper/lower triangular matrix and \c B is a general matrix. + void TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, + const ScalarType alpha, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb) const; + + //! Solves the matrix equations: \c op(A)*X=alpha*B or \c X*op(A)=alpha*B where \c X and \c B are \c m by \c n matrices, \c A is a unit/non-unit, upper/lower triangular matrix and \c op(A) is \c A or \c A'. The matrix \c X is overwritten on \c B. + void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, + const ScalarType alpha, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb) const; + //@} + }; + +//------------------------------------------------------------------------------------------ +// LEVEL 1 BLAS ROUTINES +//------------------------------------------------------------------------------------------ + + template + void BLAS::ROTG(ScalarType* da, ScalarType* db, MagnitudeType* c, ScalarType* s) const + { + ScalarType roe, scale, r; + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + + if ( ScalarTraits::magnitude( *da ) > ScalarTraits::magnitude( *db ) ) { roe = *da; } + scale = ScalarTraits::magnitude( *da ) + ScalarTraits::magnitude( *db ); + if ( scale == zero ) // There is nothing to do. + { + *c = one; + *s = zero; + *da = zero; *db = zero; + } else { // Compute the Givens rotation. + r = scale*ScalarTraits::squareroot( ( *da/scale)*(*da/scale) + (*db/scale)*(*db/scale) ); + if ( roe < zero ) { r *= -one; } + *c = *da / r; + *s = *db / r; + *db = ScalarTraits::one(); + if( ScalarTraits::magnitude( *da ) > ScalarTraits::magnitude( *db ) ){ *db = *s; } + if( ScalarTraits::magnitude( *db ) >= ScalarTraits::magnitude( *da ) && + *c != ScalarTraits::zero() ) { *db = one / *c; } + *da = r; + } + } /* end ROTG */ + + template + void BLAS::ROT(const OrdinalType n, ScalarType* dx, const OrdinalType incx, ScalarType* dy, const OrdinalType incy, MagnitudeType* c, ScalarType* s) const + { + // ToDo: Implement this. + } + + template + void BLAS::SCAL(const OrdinalType n, const ScalarType alpha, ScalarType* x, const OrdinalType incx) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + OrdinalType i, ix = izero; + if ( n > izero ) { + // Set the initial index (ix). + if (incx < izero) { ix = (-n+ione)*incx; } + // Scale the std::vector. + for(i = izero; i < n; i++) + { + x[ix] *= alpha; + ix += incx; + } + } + } /* end SCAL */ + + template + void BLAS::COPY(const OrdinalType n, const ScalarType* x, const OrdinalType incx, ScalarType* y, const OrdinalType incy) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + OrdinalType i, ix = izero, iy = izero; + if ( n > izero ) { + // Set the initial indices (ix, iy). + if (incx < izero) { ix = (-n+ione)*incx; } + if (incy < izero) { iy = (-n+ione)*incy; } + + for(i = izero; i < n; i++) + { + y[iy] = x[ix]; + ix += incx; + iy += incy; + } + } + } /* end COPY */ + + template + void BLAS::AXPY(const OrdinalType n, const ScalarType alpha, const ScalarType* x, const OrdinalType incx, ScalarType* y, const OrdinalType incy) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + OrdinalType i, ix = izero, iy = izero; + if( n > izero && alpha != ScalarTraits::zero()) + { + // Set the initial indices (ix, iy). + if (incx < izero) { ix = (-n+ione)*incx; } + if (incy < izero) { iy = (-n+ione)*incy; } + + for(i = izero; i < n; i++) + { + y[iy] += alpha * x[ix]; + ix += incx; + iy += incy; + } + } + } /* end AXPY */ + + template + typename ScalarTraits::magnitudeType BLAS::ASUM(const OrdinalType n, const ScalarType* x, const OrdinalType incx) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + typename ScalarTraits::magnitudeType result = + ScalarTraits::magnitudeType>::zero(); + OrdinalType i, ix = izero; + if( n > izero ) { + // Set the initial indices + if (incx < izero) { ix = (-n+ione)*incx; } + + for(i = izero; i < n; i++) + { + result += ScalarTraits::magnitude(x[ix]); + ix += incx; + } + } + return result; + } /* end ASUM */ + + template + ScalarType BLAS::DOT(const OrdinalType n, const ScalarType* x, const OrdinalType incx, const ScalarType* y, const OrdinalType incy) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType result = ScalarTraits::zero(); + OrdinalType i, ix = izero, iy = izero; + if( n > izero ) + { + // Set the initial indices (ix,iy). + if (incx < izero) { ix = (-n+ione)*incx; } + if (incy < izero) { iy = (-n+ione)*incy; } + + for(i = izero; i < n; i++) + { + result += ScalarTraits::conjugate(x[ix]) * y[iy]; + ix += incx; + iy += incy; + } + } + return result; + } /* end DOT */ + + template + typename ScalarTraits::magnitudeType BLAS::NRM2(const OrdinalType n, const ScalarType* x, const OrdinalType incx) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + typename ScalarTraits::magnitudeType result = + ScalarTraits::magnitudeType>::zero(); + OrdinalType i, ix = izero; + if ( n > izero ) + { + // Set the initial index. + if (incx < izero) { ix = (-n+ione)*incx; } + + for(i = izero; i < n; i++) + { + result += ScalarTraits::conjugate(x[ix]) * x[ix]; + ix += incx; + } + result = ScalarTraits::squareroot(result); + } + return result; + } /* end NRM2 */ + + template + OrdinalType BLAS::IAMAX(const OrdinalType n, const ScalarType* x, const OrdinalType incx) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + OrdinalType result = izero, ix = izero, i; + ScalarType maxval; + + if ( n > izero ) + { + if (incx < izero) { ix = (-n+ione)*incx; } + maxval = ScalarTraits::magnitude(x[ix]); + ix += incx; + for(i = ione; i < n; i++) + { + if(ScalarTraits::magnitude(x[ix]) > maxval) + { + result = i; + maxval = ScalarTraits::magnitude(x[ix]); + } + ix += incx; + } + } + return result + 1; // the BLAS I?AMAX functions return 1-indexed (Fortran-style) values + } /* end IAMAX */ + +//------------------------------------------------------------------------------------------ +// LEVEL 2 BLAS ROUTINES +//------------------------------------------------------------------------------------------ + + template + void BLAS::GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, const ScalarType* x, const OrdinalType incx, const ScalarType beta, ScalarType* y, const OrdinalType incy) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + bool BadArgument = false; + + // Quick return if there is nothing to do! + if( m == izero || n == izero || ( alpha == zero && beta == one ) ){ return; } + + // Otherwise, we need to check the argument list. + if( m < izero ) { + std::cout << "BLAS::GEMV Error: M == " << m << std::endl; + BadArgument = true; + } + if( n < izero ) { + std::cout << "BLAS::GEMV Error: N == " << n << std::endl; + BadArgument = true; + } + if( lda < m ) { + std::cout << "BLAS::GEMV Error: LDA < MAX(1,M)"<< std::endl; + BadArgument = true; + } + if( incx == izero ) { + std::cout << "BLAS::GEMV Error: INCX == 0"<< std::endl; + BadArgument = true; + } + if( incy == izero ) { + std::cout << "BLAS::GEMV Error: INCY == 0"<< std::endl; + BadArgument = true; + } + + if(!BadArgument) { + OrdinalType i, j, lenx, leny, ix, iy, jx, jy; + OrdinalType kx = izero, ky = izero; + ScalarType temp; + + // Determine the lengths of the vectors x and y. + if(ETranspChar[trans] == 'N') { + lenx = n; + leny = m; + } else { + lenx = m; + leny = n; + } + + // Set the starting pointers for the vectors x and y if incx/y < 0. + if (incx < izero ) { kx = (ione - lenx)*incx; } + if (incy < izero ) { ky = (ione - leny)*incy; } + + // Form y = beta*y + ix = kx; iy = ky; + if(beta != one) { + if (incy == ione) { + if (beta == zero) { + for(i = izero; i < leny; i++) { y[i] = zero; } + } else { + for(i = izero; i < leny; i++) { y[i] *= beta; } + } + } else { + if (beta == zero) { + for(i = izero; i < leny; i++) { + y[iy] = zero; + iy += incy; + } + } else { + for(i = izero; i < leny; i++) { + y[iy] *= beta; + iy += incy; + } + } + } + } + + // Return if we don't have to do anything more. + if(alpha == zero) { return; } + + if( ETranspChar[trans] == 'N' ) { + // Form y = alpha*A*y + jx = kx; + if (incy == ione) { + for(j = izero; j < n; j++) { + if (x[jx] != zero) { + temp = alpha*x[jx]; + for(i = izero; i < m; i++) { + y[i] += temp*A[j*lda + i]; + } + } + jx += incx; + } + } else { + for(j = izero; j < n; j++) { + if (x[jx] != zero) { + temp = alpha*x[jx]; + iy = ky; + for(i = izero; i < m; i++) { + y[iy] += temp*A[j*lda + i]; + iy += incy; + } + } + jx += incx; + } + } + } else { + jy = ky; + if (incx == ione) { + for(j = izero; j < n; j++) { + temp = zero; + for(i = izero; i < m; i++) { + temp += A[j*lda + i]*x[i]; + } + y[jy] += alpha*temp; + jy += incy; + } + } else { + for(j = izero; j < n; j++) { + temp = zero; + ix = kx; + for (i = izero; i < m; i++) { + temp += A[j*lda + i]*x[ix]; + ix += incx; + } + y[jy] += alpha*temp; + jy += incy; + } + } + } + } /* if (!BadArgument) */ + } /* end GEMV */ + + template + void BLAS::TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const ScalarType* A, const OrdinalType lda, ScalarType* x, const OrdinalType incx) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + bool BadArgument = false; + + // Quick return if there is nothing to do! + if( n == izero ){ return; } + + // Otherwise, we need to check the argument list. + if( n < izero ) { + std::cout << "BLAS::TRMV Error: N == " << n << std::endl; + BadArgument = true; + } + if( lda < n ) { + std::cout << "BLAS::TRMV Error: LDA < MAX(1,N)"<< std::endl; + BadArgument = true; + } + if( incx == izero ) { + std::cout << "BLAS::TRMV Error: INCX == 0"<< std::endl; + BadArgument = true; + } + + if(!BadArgument) { + OrdinalType i, j, ix, jx, kx = izero; + ScalarType temp; + bool NoUnit = (EDiagChar[diag] == 'N'); + + // Set the starting pointer for the std::vector x if incx < 0. + if (incx < izero) { kx = (-n+ione)*incx; } + + // Start the operations for a nontransposed triangular matrix + if (ETranspChar[trans] == 'N') { + /* Compute x = A*x */ + if (EUploChar[uplo] == 'U') { + /* A is an upper triangular matrix */ + if (incx == ione) { + for (j=izero; j-ione; j--) { + if (x[j] != zero) { + temp = x[j]; + for (i=n-ione; i>j; i--) { + x[i] += temp*A[j*lda + i]; + } + if (NoUnit) + x[j] *= A[j*lda + j]; + } + } + } else { + kx += (n-ione)*incx; + jx = kx; + for (j=n-ione; j>-ione; j--) { + if (x[jx] != zero) { + temp = x[jx]; + ix = kx; + for (i=n-ione; i>j; i--) { + x[ix] += temp*A[j*lda + i]; + ix -= incx; + } + if (NoUnit) + x[jx] *= A[j*lda + j]; + } + jx -= incx; + } + } + } /* if (EUploChar[uplo]=='U') */ + } else { /* A is transposed/conjugated */ + /* Compute x = A'*x */ + if (EUploChar[uplo]=='U') { + /* A is an upper triangular matrix */ + if (incx == ione) { + for (j=n-ione; j>-ione; j--) { + temp = x[j]; + if (NoUnit) + temp *= A[j*lda + j]; + for (i=j-ione; i>-ione; i--) { + temp += A[j*lda + i]*x[i]; + } + x[j] = temp; + } + } else { + jx = kx + (n-ione)*incx; + for (j=n-ione; j>-ione; j--) { + temp = x[jx]; + ix = jx; + if (NoUnit) + temp *= A[j*lda + j]; + for (i=j-ione; i>-ione; i--) { + ix -= incx; + temp += A[j*lda + i]*x[ix]; + } + x[jx] = temp; + jx -= incx; + } + } + } else { + /* A is a lower triangular matrix */ + if (incx == ione) { + for (j=izero; j + void BLAS::GER(const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* x, const OrdinalType incx, const ScalarType* y, const OrdinalType incy, ScalarType* A, const OrdinalType lda) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + bool BadArgument = false; + + // Quick return if there is nothing to do! + if( m == izero || n == izero || alpha == zero ){ return; } + + // Otherwise, we need to check the argument list. + if( m < izero ) { + std::cout << "BLAS::GER Error: M == " << m << std::endl; + BadArgument = true; + } + if( n < izero ) { + std::cout << "BLAS::GER Error: N == " << n << std::endl; + BadArgument = true; + } + if( lda < m ) { + std::cout << "BLAS::GER Error: LDA < MAX(1,M)"<< std::endl; + BadArgument = true; + } + if( incx == 0 ) { + std::cout << "BLAS::GER Error: INCX == 0"<< std::endl; + BadArgument = true; + } + if( incy == 0 ) { + std::cout << "BLAS::GER Error: INCY == 0"<< std::endl; + BadArgument = true; + } + + if(!BadArgument) { + OrdinalType i, j, ix, jy = izero, kx = izero; + ScalarType temp; + + // Set the starting pointers for the vectors x and y if incx/y < 0. + if (incx < izero) { kx = (-m+ione)*incx; } + if (incy < izero) { jy = (-n+ione)*incy; } + + // Start the operations for incx == 1 + if( incx == ione ) { + for( j=izero; j + void BLAS::GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, const ScalarType* B, const OrdinalType ldb, const ScalarType beta, ScalarType* C, const OrdinalType ldc) const + { + OrdinalType izero = OrdinalTraits::zero(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + OrdinalType i, j, p; + OrdinalType NRowA = m, NRowB = k; + ScalarType temp; + bool BadArgument = false; + + // Change dimensions of matrix if either matrix is transposed + if( !(ETranspChar[transa]=='N') ) { + NRowA = k; + } + if( !(ETranspChar[transb]=='N') ) { + NRowB = n; + } + + // Quick return if there is nothing to do! + if( (m==izero) || (n==izero) || (((alpha==zero)||(k==izero)) && (beta==one)) ){ return; } + if( m < izero ) { + std::cout << "BLAS::GEMM Error: M == " << m << std::endl; + BadArgument = true; + } + if( n < izero ) { + std::cout << "BLAS::GEMM Error: N == " << n << std::endl; + BadArgument = true; + } + if( k < izero ) { + std::cout << "BLAS::GEMM Error: K == " << k << std::endl; + BadArgument = true; + } + if( lda < NRowA ) { + std::cout << "BLAS::GEMM Error: LDA < MAX(1,M)"<< std::endl; + BadArgument = true; + } + if( ldb < NRowB ) { + std::cout << "BLAS::GEMM Error: LDB < MAX(1,K)"<< std::endl; + BadArgument = true; + } + if( ldc < m ) { + std::cout << "BLAS::GEMM Error: LDC < MAX(1,M)"<< std::endl; + BadArgument = true; + } + + if(!BadArgument) { + + // Only need to scale the resulting matrix C. + if( alpha == zero ) { + if( beta == zero ) { + for (j=izero; j + void BLAS::SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, const ScalarType* B, const OrdinalType ldb, const ScalarType beta, ScalarType* C, const OrdinalType ldc) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + OrdinalType i, j, k, NRowA = m; + ScalarType temp1, temp2; + bool BadArgument = false; + bool Upper = (EUploChar[uplo] == 'U'); + if (ESideChar[side] == 'R') { NRowA = n; } + + // Quick return. + if ( (m==izero) || (n==izero) || ( (alpha==zero)&&(beta==one) ) ) { return; } + if( m < 0 ) { + std::cout << "BLAS::SYMM Error: M == "<< m << std::endl; + BadArgument = true; } + if( n < 0 ) { + std::cout << "BLAS::SYMM Error: N == "<< n << std::endl; + BadArgument = true; } + if( lda < NRowA ) { + std::cout << "BLAS::SYMM Error: LDA == "<-ione; i--) { + temp1 = alpha*B[j*ldb + i]; + temp2 = zero; + for (k=i+ione; k + void BLAS::TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + OrdinalType i, j, k, NRowA = m; + ScalarType temp; + bool BadArgument = false; + bool LSide = (ESideChar[side] == 'L'); + bool NoUnit = (EDiagChar[diag] == 'N'); + bool Upper = (EUploChar[uplo] == 'U'); + + if(!LSide) { NRowA = n; } + + // Quick return. + if (n==izero || m==izero) { return; } + if( m < 0 ) { + std::cout << "BLAS::TRMM Error: M == "<< m <-ione; k-- ) { + if( B[j*ldb + k] != zero ) { + temp = alpha*B[j*ldb + k]; + B[j*ldb + k] = temp; + if ( NoUnit ) + B[j*ldb + k] *= A[k*lda + k]; + for( i=k+ione; i-ione; i-- ) { + temp = B[j*ldb + i]; + if( NoUnit ) + temp *= A[i*lda + i]; + for( k=izero; k-ione; j-- ) { + temp = alpha; + if( NoUnit ) + temp *= A[j*lda + j]; + for( i=izero; i-ione; k-- ) { + for( j=k+ione; j + void BLAS::TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const ScalarType alpha, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb) const + { + OrdinalType izero = OrdinalTraits::zero(); + OrdinalType ione = OrdinalTraits::one(); + ScalarType zero = ScalarTraits::zero(); + ScalarType one = ScalarTraits::one(); + ScalarType temp; + OrdinalType NRowA = m; + bool BadArgument = false; + bool NoUnit = (EDiagChar[diag]=='N'); + + if (!(ESideChar[side] == 'L')) { NRowA = n; } + + // Quick return. + if (n == izero || m == izero) { return; } + if( m < izero ) { + std::cout << "BLAS::TRSM Error: M == "< -ione; k--) { + // If this entry is zero, we don't have to do anything. + if (B[j*ldb + k] != zero) { + if (NoUnit) { + B[j*ldb + k] /= A[k*lda + k]; + } + for(i = izero; i < k; i++) { + B[j*ldb + i] -= B[j*ldb + k] * A[k*lda + i]; + } + } + } + } + } + else + { // A is lower triangular. + for(j = izero; j < n; j++) { + // Perform alpha*B if alpha is not 1. + if(alpha != one) { + for( i = izero; i < m; i++) { + B[j*ldb+i] *= alpha; + } + } + // Perform a forward solve for column j of B. + for(k = izero; k < m; k++) { + // If this entry is zero, we don't have to do anything. + if (B[j*ldb + k] != zero) { + if (NoUnit) { + B[j*ldb + k] /= A[k*lda + k]; + } + for(i = k+ione; i < m; i++) { + B[j*ldb + i] -= B[j*ldb + k] * A[k*lda + i]; + } + } + } + } + } // end if (uplo == 'U') + } // if (transa =='N') + else { + // + // Compute B = alpha*inv( A' )*B + // + if(EUploChar[uplo] == 'U') { + // A is upper triangular. + for(j = izero; j < n; j++) { + for( i = izero; i < m; i++) { + temp = alpha*B[j*ldb+i]; + for(k = izero; k < i; k++) { + temp -= A[i*lda + k] * B[j*ldb + k]; + } + if (NoUnit) { + temp /= A[i*lda + i]; + } + B[j*ldb + i] = temp; + } + } + } + else + { // A is lower triangular. + for(j = izero; j < n; j++) { + for(i = (m - ione) ; i > -ione; i--) { + temp = alpha*B[j*ldb+i]; + for(k = i+ione; k < m; k++) { + temp -= A[i*lda + k] * B[j*ldb + k]; + } + if (NoUnit) { + temp /= A[i*lda + i]; + } + B[j*ldb + i] = temp; + } + } + } + } + } // if (side == 'L') + else { + // side == 'R' + // + // Perform computations for X*OP(A) = alpha*B + // + if (ETranspChar[transa] == 'N') { + // + // Compute B = alpha*B*inv( A ) + // + if(EUploChar[uplo] == 'U') { + // A is upper triangular. + // Perform a backsolve for column j of B. + for(j = izero; j < n; j++) { + // Perform alpha*B if alpha is not 1. + if(alpha != one) { + for( i = izero; i < m; i++) { + B[j*ldb+i] *= alpha; + } + } + for(k = izero; k < j; k++) { + // If this entry is zero, we don't have to do anything. + if (A[j*lda + k] != zero) { + for(i = izero; i < m; i++) { + B[j*ldb + i] -= A[j*lda + k] * B[k*ldb + i]; + } + } + } + if (NoUnit) { + temp = one/A[j*lda + j]; + for(i = izero; i < m; i++) { + B[j*ldb + i] *= temp; + } + } + } + } + else + { // A is lower triangular. + for(j = (n - ione); j > -ione; j--) { + // Perform alpha*B if alpha is not 1. + if(alpha != one) { + for( i = izero; i < m; i++) { + B[j*ldb+i] *= alpha; + } + } + // Perform a forward solve for column j of B. + for(k = j+ione; k < n; k++) { + // If this entry is zero, we don't have to do anything. + if (A[j*lda + k] != zero) { + for(i = izero; i < m; i++) { + B[j*ldb + i] -= A[j*lda + k] * B[k*ldb + i]; + } + } + } + if (NoUnit) { + temp = one/A[j*lda + j]; + for(i = izero; i < m; i++) { + B[j*ldb + i] *= temp; + } + } + } + } // end if (uplo == 'U') + } // if (transa =='N') + else { + // + // Compute B = alpha*B*inv( A' ) + // + if(EUploChar[uplo] == 'U') { + // A is upper triangular. + for(k = (n - ione); k > -ione; k--) { + if (NoUnit) { + temp = one/A[k*lda + k]; + for(i = izero; i < m; i++) { + B[k*ldb + i] *= temp; + } + } + for(j = izero; j < k; j++) { + if (A[k*lda + j] != zero) { + temp = A[k*lda + j]; + for(i = izero; i < m; i++) { + B[j*ldb + i] -= temp*B[k*ldb + i]; + } + } + } + if (alpha != one) { + for (i = izero; i < m; i++) { + B[k*ldb + i] *= alpha; + } + } + } + } + else + { // A is lower triangular. + for(k = izero; k < n; k++) { + if (NoUnit) { + temp = one/A[k*lda + k]; + for (i = izero; i < m; i++) { + B[k*ldb + i] *= temp; + } + } + for(j = k+ione; j < n; j++) { + if(A[k*lda + j] != zero) { + temp = A[k*lda + j]; + for(i = izero; i < m; i++) { + B[j*ldb + i] -= temp*B[k*ldb + i]; + } + } + } + if (alpha != one) { + for (i = izero; i < m; i++) { + B[k*ldb + i] *= alpha; + } + } + } + } + } + } + } + } + } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +#ifdef HAVE_TEUCHOS_BLASFLOAT + + template + class BLAS + { + public: + inline BLAS(void) {} + inline BLAS(const BLAS& BLAS_source) {} + inline virtual ~BLAS(void) {} + void ROTG(float* da, float* db, float* c, float* s) const; + void ROT(const OrdinalType n, float* dx, const OrdinalType incx, float* dy, const OrdinalType incy, float* c, float* s) const; + float ASUM(const OrdinalType n, const float* x, const OrdinalType incx) const; + void AXPY(const OrdinalType n, const float alpha, const float* x, const OrdinalType incx, float* y, const OrdinalType incy) const; + void COPY(const OrdinalType n, const float* x, const OrdinalType incx, float* y, const OrdinalType incy) const; + float DOT(const OrdinalType n, const float* x, const OrdinalType incx, const float* y, const OrdinalType incy) const; + float NRM2(const OrdinalType n, const float* x, const OrdinalType incx) const; + void SCAL(const OrdinalType n, const float alpha, float* x, const OrdinalType incx) const; + OrdinalType IAMAX(const OrdinalType n, const float* x, const OrdinalType incx) const; + void GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, const float* x, const OrdinalType incx, const float beta, float* y, const OrdinalType incy) const; + void TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const float* A, const OrdinalType lda, float* x, const OrdinalType incx) const; + void GER(const OrdinalType m, const OrdinalType n, const float alpha, const float* x, const OrdinalType incx, const float* y, const OrdinalType incy, float* A, const OrdinalType lda) const; + void GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const float alpha, const float* A, const OrdinalType lda, const float* B, const OrdinalType ldb, const float beta, float* C, const OrdinalType ldc) const; + void SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, const float *B, const OrdinalType ldb, const float beta, float *C, const OrdinalType ldc) const; + void TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb) const; + void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb) const; + }; + + template + void BLAS::ROTG(float* da, float* db, float* c, float* s) const + { SROTG_F77(da, db, c, s ); } + + template + void BLAS::ROT(const OrdinalType n, float* dx, const OrdinalType incx, float* dy, const OrdinalType incy, float* c, float* s) const + { SROT_F77(&n, dx, &incx, dy, &incy, c, s); } + + template + float BLAS::ASUM(const OrdinalType n, const float* x, const OrdinalType incx) const + { + float tmp = SASUM_F77(&n, x, &incx); + return tmp; + } + + template + void BLAS::AXPY(const OrdinalType n, const float alpha, const float* x, const OrdinalType incx, float* y, const OrdinalType incy) const + { SAXPY_F77(&n, &alpha, x, &incx, y, &incy); } + + template + void BLAS::COPY(const OrdinalType n, const float* x, const OrdinalType incx, float* y, const OrdinalType incy) const + { SCOPY_F77(&n, x, &incx, y, &incy); } + + template + float BLAS::DOT(const OrdinalType n, const float* x, const OrdinalType incx, const float* y, const OrdinalType incy) const + { return SDOT_F77(&n, x, &incx, y, &incy); } + + template + OrdinalType BLAS::IAMAX(const OrdinalType n, const float* x, const OrdinalType incx) const + { return ISAMAX_F77(&n, x, &incx); } + + template + float BLAS::NRM2(const OrdinalType n, const float* x, const OrdinalType incx) const + { return SNRM2_F77(&n, x, &incx); } + + template + void BLAS::SCAL(const OrdinalType n, const float alpha, float* x, const OrdinalType incx) const + { SSCAL_F77(&n, &alpha, x, &incx); } + + template + void BLAS::GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, const float* x, const OrdinalType incx, const float beta, float* y, const OrdinalType incy) const + { SGEMV_F77(CHAR_MACRO(ETranspChar[trans]), &m, &n, &alpha, A, &lda, x, &incx, &beta, y, &incy); } + + template + void BLAS::GER(const OrdinalType m, const OrdinalType n, const float alpha, const float* x, const OrdinalType incx, const float* y, const OrdinalType incy, float* A, const OrdinalType lda) const + { SGER_F77(&m, &n, &alpha, x, &incx, y, &incy, A, &lda); } + + template + void BLAS::TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const float* A, const OrdinalType lda, float* x, const OrdinalType incx) const + { STRMV_F77(CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[trans]), CHAR_MACRO(EDiagChar[diag]), &n, A, &lda, x, &incx); } + + template + void BLAS::GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const float alpha, const float* A, const OrdinalType lda, const float* B, const OrdinalType ldb, const float beta, float* C, const OrdinalType ldc) const + { SGEMM_F77(CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(ETranspChar[transb]), &m, &n, &k, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS::SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, const float* B, const OrdinalType ldb, const float beta, float* C, const OrdinalType ldc) const + { SSYMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), &m, &n, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS::TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb) const + { STRMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + + template + void BLAS::TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const float alpha, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb) const + { STRSM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + +#endif // HAVE_TEUCHOS_BLASFLOAT + + template + class BLAS + { + public: + inline BLAS(void) {} + inline BLAS(const BLAS& BLAS_source) {} + inline virtual ~BLAS(void) {} + void ROTG(double* da, double* db, double* c, double* s) const; + void ROT(const OrdinalType n, double* dx, const OrdinalType incx, double* dy, const OrdinalType incy, double* c, double* s) const; + double ASUM(const OrdinalType n, const double* x, const OrdinalType incx) const; + void AXPY(const OrdinalType n, const double alpha, const double* x, const OrdinalType incx, double* y, const OrdinalType incy) const; + void COPY(const OrdinalType n, const double* x, const OrdinalType incx, double* y, const OrdinalType incy) const; + double DOT(const OrdinalType n, const double* x, const OrdinalType incx, const double* y, const OrdinalType incy) const; + double NRM2(const OrdinalType n, const double* x, const OrdinalType incx) const; + void SCAL(const OrdinalType n, const double alpha, double* x, const OrdinalType incx) const; + OrdinalType IAMAX(const OrdinalType n, const double* x, const OrdinalType incx) const; + void GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, const double* x, const OrdinalType incx, const double beta, double* y, const OrdinalType incy) const; + void TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const double* A, const OrdinalType lda, double* x, const OrdinalType incx) const; + void GER(const OrdinalType m, const OrdinalType n, const double alpha, const double* x, const OrdinalType incx, const double* y, const OrdinalType incy, double* A, const OrdinalType lda) const; + void GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const double alpha, const double* A, const OrdinalType lda, const double* B, const OrdinalType ldb, const double beta, double* C, const OrdinalType ldc) const; + void SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, const double *B, const OrdinalType ldb, const double beta, double *C, const OrdinalType ldc) const; + void TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb) const; + void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb) const; + }; + + template + void BLAS::ROTG(double* da, double* db, double* c, double* s) const + { DROTG_F77(da, db, c, s); } + + template + void BLAS::ROT(const OrdinalType n, double* dx, const OrdinalType incx, double* dy, const OrdinalType incy, double* c, double* s) const + { DROT_F77(&n, dx, &incx, dy, &incy, c, s); } + + template + double BLAS::ASUM(const OrdinalType n, const double* x, const OrdinalType incx) const + { return DASUM_F77(&n, x, &incx); } + + template + void BLAS::AXPY(const OrdinalType n, const double alpha, const double* x, const OrdinalType incx, double* y, const OrdinalType incy) const + { DAXPY_F77(&n, &alpha, x, &incx, y, &incy); } + + template + void BLAS::COPY(const OrdinalType n, const double* x, const OrdinalType incx, double* y, const OrdinalType incy) const + { DCOPY_F77(&n, x, &incx, y, &incy); } + + template + double BLAS::DOT(const OrdinalType n, const double* x, const OrdinalType incx, const double* y, const OrdinalType incy) const + { return DDOT_F77(&n, x, &incx, y, &incy); } + + template + OrdinalType BLAS::IAMAX(const OrdinalType n, const double* x, const OrdinalType incx) const + { return IDAMAX_F77(&n, x, &incx); } + + template + double BLAS::NRM2(const OrdinalType n, const double* x, const OrdinalType incx) const + { return DNRM2_F77(&n, x, &incx); } + + template + void BLAS::SCAL(const OrdinalType n, const double alpha, double* x, const OrdinalType incx) const + { DSCAL_F77(&n, &alpha, x, &incx); } + + template + void BLAS::GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, const double* x, const OrdinalType incx, const double beta, double* y, const OrdinalType incy) const + { DGEMV_F77(CHAR_MACRO(ETranspChar[trans]), &m, &n, &alpha, A, &lda, x, &incx, &beta, y, &incy); } + + template + void BLAS::GER(const OrdinalType m, const OrdinalType n, const double alpha, const double* x, const OrdinalType incx, const double* y, const OrdinalType incy, double* A, const OrdinalType lda) const + { DGER_F77(&m, &n, &alpha, x, &incx, y, &incy, A, &lda); } + + template + void BLAS::TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const double* A, const OrdinalType lda, double* x, const OrdinalType incx) const + { DTRMV_F77(CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[trans]), CHAR_MACRO(EDiagChar[diag]), &n, A, &lda, x, &incx); } + + template + void BLAS::GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const double alpha, const double* A, const OrdinalType lda, const double* B, const OrdinalType ldb, const double beta, double* C, const OrdinalType ldc) const + { DGEMM_F77(CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(ETranspChar[transb]), &m, &n, &k, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS::SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, const double *B, const OrdinalType ldb, const double beta, double *C, const OrdinalType ldc) const + { DSYMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), &m, &n, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS::TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb) const + { DTRMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + + template + void BLAS::TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const double alpha, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb) const + { DTRSM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + +#ifdef HAVE_TEUCHOS_COMPLEX + +#ifdef HAVE_TEUCHOS_BLASFLOAT + + template + class BLAS > + { + public: + inline BLAS(void) {} + inline BLAS(const BLAS >& BLAS_source) {} + inline virtual ~BLAS(void) {} + void ROTG(std::complex* da, std::complex* db, float* c, std::complex* s) const; + void ROT(const OrdinalType n, std::complex* dx, const OrdinalType incx, std::complex* dy, const OrdinalType incy, float* c, std::complex* s) const; + float ASUM(const OrdinalType n, const std::complex* x, const OrdinalType incx) const; + void AXPY(const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const; + void COPY(const OrdinalType n, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const; + std::complex DOT(const OrdinalType n, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy) const; + float NRM2(const OrdinalType n, const std::complex* x, const OrdinalType incx) const; + void SCAL(const OrdinalType n, const std::complex alpha, std::complex* x, const OrdinalType incx) const; + OrdinalType IAMAX(const OrdinalType n, const std::complex* x, const OrdinalType incx) const; + void GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* x, const OrdinalType incx, const std::complex beta, std::complex* y, const OrdinalType incy) const; + void TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const std::complex* A, const OrdinalType lda, std::complex* x, const OrdinalType incx) const; + void GER(const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy, std::complex* A, const OrdinalType lda) const; + void GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* B, const OrdinalType ldb, const std::complex beta, std::complex* C, const OrdinalType ldc) const; + void SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex *B, const OrdinalType ldb, const std::complex beta, std::complex *C, const OrdinalType ldc) const; + void TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const; + void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const; + }; + + template + void BLAS >::ROTG(std::complex* da, std::complex* db, float* c, std::complex* s) const + { CROTG_F77(da, db, c, s ); } + + template + void BLAS >::ROT(const OrdinalType n, std::complex* dx, const OrdinalType incx, std::complex* dy, const OrdinalType incy, float* c, std::complex* s) const + { CROT_F77(&n, dx, &incx, dy, &incy, c, s); } + + template + float BLAS >::ASUM(const OrdinalType n, const std::complex* x, const OrdinalType incx) const + { return CASUM_F77(&n, x, &incx); } + + template + void BLAS >::AXPY(const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const + { CAXPY_F77(&n, &alpha, x, &incx, y, &incy); } + + template + void BLAS >::COPY(const OrdinalType n, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const + { CCOPY_F77(&n, x, &incx, y, &incy); } + + template + std::complex BLAS >::DOT(const OrdinalType n, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy) const + { return CDOT_F77(&n, x, &incx, y, &incy); } + + template + OrdinalType BLAS >::IAMAX(const OrdinalType n, const std::complex* x, const OrdinalType incx) const + { return ICAMAX_F77(&n, x, &incx); } + + template + float BLAS >::NRM2(const OrdinalType n, const std::complex* x, const OrdinalType incx) const + { return CNRM2_F77(&n, x, &incx); } + + template + void BLAS >::SCAL(const OrdinalType n, const std::complex alpha, std::complex* x, const OrdinalType incx) const + { CSCAL_F77(&n, &alpha, x, &incx); } + + template + void BLAS >::GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* x, const OrdinalType incx, const std::complex beta, std::complex* y, const OrdinalType incy) const + { CGEMV_F77(CHAR_MACRO(ETranspChar[trans]), &m, &n, &alpha, A, &lda, x, &incx, &beta, y, &incy); } + + template + void BLAS >::GER(const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy, std::complex* A, const OrdinalType lda) const + { CGER_F77(&m, &n, &alpha, x, &incx, y, &incy, A, &lda); } + + template + void BLAS >::TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const std::complex* A, const OrdinalType lda, std::complex* x, const OrdinalType incx) const + { CTRMV_F77(CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[trans]), CHAR_MACRO(EDiagChar[diag]), &n, A, &lda, x, &incx); } + + template + void BLAS >::GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* B, const OrdinalType ldb, const std::complex beta, std::complex* C, const OrdinalType ldc) const + { CGEMM_F77(CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(ETranspChar[transb]), &m, &n, &k, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS >::SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* B, const OrdinalType ldb, const std::complex beta, std::complex* C, const OrdinalType ldc) const + { CSYMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), &m, &n, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS >::TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const + { CTRMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + + template + void BLAS >::TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const + { CTRSM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + +#endif // HAVE_TEUCHOS_BLASFLOAT + + template + class BLAS > + { + public: + inline BLAS(void) {} + inline BLAS(const BLAS >& BLAS_source) {} + inline virtual ~BLAS(void) {} + void ROTG(std::complex* da, std::complex* db, double* c, std::complex* s) const; + void ROT(const OrdinalType n, std::complex* dx, const OrdinalType incx, std::complex* dy, const OrdinalType incy, double* c, std::complex* s) const; + double ASUM(const OrdinalType n, const std::complex* x, const OrdinalType incx) const; + void AXPY(const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const; + void COPY(const OrdinalType n, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const; + std::complex DOT(const OrdinalType n, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy) const; + double NRM2(const OrdinalType n, const std::complex* x, const OrdinalType incx) const; + void SCAL(const OrdinalType n, const std::complex alpha, std::complex* x, const OrdinalType incx) const; + OrdinalType IAMAX(const OrdinalType n, const std::complex* x, const OrdinalType incx) const; + void GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* x, const OrdinalType incx, const std::complex beta, std::complex* y, const OrdinalType incy) const; + void TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const std::complex* A, const OrdinalType lda, std::complex* x, const OrdinalType incx) const; + void GER(const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy, std::complex* A, const OrdinalType lda) const; + void GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* B, const OrdinalType ldb, const std::complex beta, std::complex* C, const OrdinalType ldc) const; + void SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex *B, const OrdinalType ldb, const std::complex beta, std::complex *C, const OrdinalType ldc) const; + void TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const; + void TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const; + }; + + template + void BLAS >::ROTG(std::complex* da, std::complex* db, double* c, std::complex* s) const + { ZROTG_F77(da, db, c, s); } + + template + void BLAS >::ROT(const OrdinalType n, std::complex* dx, const OrdinalType incx, std::complex* dy, const OrdinalType incy, double* c, std::complex* s) const + { ZROT_F77(&n, dx, &incx, dy, &incy, c, s); } + + template + double BLAS >::ASUM(const OrdinalType n, const std::complex* x, const OrdinalType incx) const + { return ZASUM_F77(&n, x, &incx); } + + template + void BLAS >::AXPY(const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const + { ZAXPY_F77(&n, &alpha, x, &incx, y, &incy); } + + template + void BLAS >::COPY(const OrdinalType n, const std::complex* x, const OrdinalType incx, std::complex* y, const OrdinalType incy) const + { ZCOPY_F77(&n, x, &incx, y, &incy); } + + template + std::complex BLAS >::DOT(const OrdinalType n, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy) const + { return ZDOT_F77(&n, x, &incx, y, &incy); } + + template + OrdinalType BLAS >::IAMAX(const OrdinalType n, const std::complex* x, const OrdinalType incx) const + { return IZAMAX_F77(&n, x, &incx); } + + template + double BLAS >::NRM2(const OrdinalType n, const std::complex* x, const OrdinalType incx) const + { return ZNRM2_F77(&n, x, &incx); } + + template + void BLAS >::SCAL(const OrdinalType n, const std::complex alpha, std::complex* x, const OrdinalType incx) const + { ZSCAL_F77(&n, &alpha, x, &incx); } + + template + void BLAS >::GEMV(ETransp trans, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* x, const OrdinalType incx, const std::complex beta, std::complex* y, const OrdinalType incy) const + { ZGEMV_F77(CHAR_MACRO(ETranspChar[trans]), &m, &n, &alpha, A, &lda, x, &incx, &beta, y, &incy); } + + template + void BLAS >::GER(const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* x, const OrdinalType incx, const std::complex* y, const OrdinalType incy, std::complex* A, const OrdinalType lda) const + { ZGER_F77(&m, &n, &alpha, x, &incx, y, &incy, A, &lda); } + + template + void BLAS >::TRMV(EUplo uplo, ETransp trans, EDiag diag, const OrdinalType n, const std::complex* A, const OrdinalType lda, std::complex* x, const OrdinalType incx) const + { ZTRMV_F77(CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[trans]), CHAR_MACRO(EDiagChar[diag]), &n, A, &lda, x, &incx); } + + template + void BLAS >::GEMM(ETransp transa, ETransp transb, const OrdinalType m, const OrdinalType n, const OrdinalType k, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex* B, const OrdinalType ldb, const std::complex beta, std::complex* C, const OrdinalType ldc) const + { ZGEMM_F77(CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(ETranspChar[transb]), &m, &n, &k, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS >::SYMM(ESide side, EUplo uplo, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, const std::complex *B, const OrdinalType ldb, const std::complex beta, std::complex *C, const OrdinalType ldc) const + { ZSYMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), &m, &n, &alpha, A, &lda, B, &ldb, &beta, C, &ldc); } + + template + void BLAS >::TRMM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const + { ZTRMM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + + template + void BLAS >::TRSM(ESide side, EUplo uplo, ETransp transa, EDiag diag, const OrdinalType m, const OrdinalType n, const std::complex alpha, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb) const + { ZTRSM_F77(CHAR_MACRO(ESideChar[side]), CHAR_MACRO(EUploChar[uplo]), CHAR_MACRO(ETranspChar[transa]), CHAR_MACRO(EDiagChar[diag]), &m, &n, &alpha, A, &lda, B, &ldb); } + +#endif // HAVE_TEUCHOS_COMPLEX + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} // namespace Teuchos + +#endif // _TEUCHOS_BLAS_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_BLAS_types.hpp b/fastlib/trilinos/include/Teuchos_BLAS_types.hpp new file mode 100644 index 0000000000..9038240281 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_BLAS_types.hpp @@ -0,0 +1,67 @@ +// ///////////////////////////////////////////// +// Teuchos_BLAS_types.hpp + +#ifndef TEUCHOS_BLAS_TYPES_HPP +#define TEUCHOS_BLAS_TYPES_HPP + +/*! \file Teuchos_BLAS_types.hpp + \brief Enumerated types for BLAS input characters. +*/ + +/*! \defgroup BLASEnum_grp Enumerations for character inputs in Teuchos::BLAS methods + + \brief These enumerated lists are used in compile time checking of the input characters + for BLAS methods. + + \note Any other input other than those specified here will result + in an error at compile time and are not supported by the templated BLAS/LAPACK interface. + +
      +
    • Teuchos::ESide : Enumerated list for BLAS character input "SIDE". +
        +
      • LEFT_SIDE : The matrix/std::vector is on, or applied to, the left side of the equation +
      • RIGHT_SIDE : The matrix/std::vector is on, or applied to, the right side of the equation +

      +
    • Teuchos::ETransp : Enumerated list for BLAS character input "TRANS". +
        +
      • NO_TRANS : The matrix/std::vector is not transposed +
      • TRANS : The matrix/std::vector is transposed +
      • CONJ_TRANS : The matrix/std::vector is conjugate transposed +

      +
    • Teuchos::EUplo : Enumerated list for BLAS character input "UPLO". +
        +
      • UPPER_TRI : The matrix is upper triangular +
      • LOWER_TRI : The matrix is lower triangular +

      +
    • Teuchos::EDiag : Enumerated list for BLAS character input "DIAG". +
        +
      • UNIT_DIAG : The matrix has all ones on its diagonal +
      • NON_UNIT_DIAG : The matrix does not have all ones on its diagonal +

      +
    +*/ + +namespace Teuchos { + enum ESide { + LEFT_SIDE, /*!< Left side */ + RIGHT_SIDE /*!< Right side */ + }; + + enum ETransp { + NO_TRANS, /*!< Not transposed */ + TRANS, /*!< Transposed */ + CONJ_TRANS /*!< Conjugate transposed */ + }; + + enum EUplo { + UPPER_TRI, /*!< Upper triangular */ + LOWER_TRI /*!< Lower triangular */ + }; + + enum EDiag { + UNIT_DIAG, /*!< Unit diagaonal */ + NON_UNIT_DIAG /*!< Not unit diagonal */ + }; +} + +#endif // TEUCHOS_BLAS_TYPES_HPP diff --git a/fastlib/trilinos/include/Teuchos_BLAS_wrappers.hpp b/fastlib/trilinos/include/Teuchos_BLAS_wrappers.hpp new file mode 100644 index 0000000000..ae7928f412 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_BLAS_wrappers.hpp @@ -0,0 +1,466 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef _TEUCHOS_BLAS_WRAPPERS_HPP_ +#define _TEUCHOS_BLAS_WRAPPERS_HPP_ + +#include "Teuchos_ConfigDefs.hpp" + +/*! \file Teuchos_BLAS_wrappers.hpp + \brief The Templated BLAS wrappers. +*/ + +/* Define fcd (Fortran Teuchos_fcd descriptor) for non-standard situations */ + +#if defined(CRAY_T3X) || defined(INTEL_CXML) || defined(INTEL_MKL) + + +#if defined(CRAY_T3X) + +#include +#define PREFIX +#define Teuchos_fcd fcd + +#define DROTG_F77 F77_FUNC(srotg,SROTG) +#define DROT_F77 F77_FUNC(srot,SROT) +#define DASUM_F77 F77_FUNC(sasum,SASUM) +#define DAXPY_F77 F77_FUNC(saxpy,SAXPY) +#define DCOPY_F77 F77_FUNC(scopy,SCOPY) +#define DDOT_F77 F77_FUNC(sdot,SDOT) +#define DNRM2_F77 F77_FUNC(snrm2,SNRM2) +#define DSCAL_F77 F77_FUNC(sscal,SSCAL) +#define IDAMAX_F77 F77_FUNC(isamax,ISAMAX) +#define DGEMV_F77 F77_FUNC(sgemv,SGEMV) +#define DGER_F77 F77_FUNC(sger,SGER) +#define DTRMV_F77 F77_FUNC(strmv,STRMV) +#define DGEMM_F77 F77_FUNC(sgemm,SGEMM) +#define DSYMM_F77 F77_FUNC(ssymm,SSYMM) +#define DTRMM_F77 F77_FUNC(strmm,STRMM) +#define DTRSM_F77 F77_FUNC(strsm,STRSM) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZROTG_F77 F77_FUNC(crotg,CROTG) +#define ZROT_F77 F77_FUNC(crot,CROT) +#define ZASUM_F77 F77_FUNC(scasum,SCASUM) +#define ZAXPY_F77 F77_FUNC(caxpy,CAXPY) +#define ZCOPY_F77 F77_FUNC(ccopy,CCOPY) +#define ZDOT_F77 F77_FUNC(cdotc,CDOTC) +#define ZNRM2_F77 F77_FUNC(scnrm2,SCNRM2) +#define ZSCAL_F77 F77_FUNC(cscal,CSCAL) +#define IZAMAX_F77 F77_FUNC(icamax,ICAMAX) +#define ZGEMV_F77 F77_FUNC(cgemv,CGEMV) +#define ZGER_F77 F77_FUNC(cgerc,CGERC) +#define ZTRMV_F77 F77_FUNC(ctrmv,CTRMV) +#define ZGEMM_F77 F77_FUNC(cgemm,CGEMM) +#define ZSYMM_F77 F77_FUNC(csymm,CSYMM) +#define ZTRMM_F77 F77_FUNC(ctrmm,CTRMM) +#define ZTRSM_F77 F77_FUNC(ctrsm,CTRSM) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#elif defined(INTEL_CXML) + +#define PREFIX __stdcall +#define Teuchos_fcd const char *, unsigned int + +#define DROTG_F77 F77_FUNC(drotg,DROTG) +#define DROT_F77 F77_FUNC(drot,DROT) +#define DASUM_F77 F77_FUNC(dasum,DASUM) +#define DAXPY_F77 F77_FUNC(daxpy,DAXPY) +#define DCOPY_F77 F77_FUNC(dcopy,DCOPY) +#define DDOT_F77 F77_FUNC(ddot,DDOT) +#define DNRM2_F77 F77_FUNC(dnrm2,DNRM2) +#define DSCAL_F77 F77_FUNC(dscal,DSCAL) +#define IDAMAX_F77 F77_FUNC(idamax,IDAMAX) +#define DGEMV_F77 F77_FUNC(dgemv,DGEMV) +#define DGER_F77 F77_FUNC(dger,DGER) +#define DTRMV_F77 F77_FUNC(dtrmv,DTRMV) +#define DGEMM_F77 F77_FUNC(dgemm,DGEMM) +#define DSYMM_F77 F77_FUNC(dsymm,DSYMM) +#define DTRMM_F77 F77_FUNC(dtrmm,DTRMM) +#define DTRSM_F77 F77_FUNC(dtrsm,DTRSM) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZROTG_F77 F77_FUNC(zrotg,ZROTG) +#define ZROT_F77 F77_FUNC(zrot,ZROT) +#define ZASUM_F77 F77_FUNC(dzasum,DZASUM) +#define ZAXPY_F77 F77_FUNC(zaxpy,ZAXPY) +#define ZCOPY_F77 F77_FUNC(zcopy,ZCOPY) +#define ZDOT_F77 F77_FUNC(zdotc,ZDOTC) +#define ZNRM2_F77 F77_FUNC(dznrm2,DZNRM2) +#define ZSCAL_F77 F77_FUNC(zscal,ZSCAL) +#define IZAMAX_F77 F77_FUNC(izamax,IZAMAX) +#define ZGEMV_F77 F77_FUNC(zgemv,ZGEMV) +#define ZGER_F77 F77_FUNC(zgerc,ZGERC) +#define ZTRMV_F77 F77_FUNC(ztrmv,ZTRMV) +#define ZGEMM_F77 F77_FUNC(zgemm,ZGEMM) +#define ZSYMM_F77 F77_FUNC(zsymm,ZSYMM) +#define ZTRMM_F77 F77_FUNC(ztrmm,ZTRMM) +#define ZTRSM_F77 F77_FUNC(ztrsm,ZTRSM) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#elif defined(INTEL_MKL) + +#define PREFIX +#define Teuchos_fcd const char * + +#define DROTG_F77 F77_FUNC(drotg,DROTG) +#define DROT_F77 F77_FUNC(drot,DROT) +#define DASUM_F77 F77_FUNC(dasum,DASUM) +#define DAXPY_F77 F77_FUNC(daxpy,DAXPY) +#define DCOPY_F77 F77_FUNC(dcopy,DCOPY) +#define DDOT_F77 F77_FUNC(ddot,DDOT) +#define DNRM2_F77 F77_FUNC(dnrm2,DNRM2) +#define DSCAL_F77 F77_FUNC(dscal,DSCAL) +#define IDAMAX_F77 F77_FUNC(idamax,IDAMAX) +#define DGEMV_F77 F77_FUNC(dgemv,DGEMV) +#define DGER_F77 F77_FUNC(dger,DGER) +#define DTRMV_F77 F77_FUNC(dtrmv,DTRMV) +#define DGEMM_F77 F77_FUNC(dgemm,DGEMM) +#define DSYMM_F77 F77_FUNC(dsymm,DSYMM) +#define DTRMM_F77 F77_FUNC(dtrmm,DTRMM) +#define DTRSM_F77 F77_FUNC(dtrsm,DTRSM) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZROTG_F77 F77_FUNC(zrotg,ZROTG) +#define ZROT_F77 F77_FUNC(zrot,ZROT) +#define ZASUM_F77 F77_FUNC(dzasum,DZASUM) +#define ZAXPY_F77 F77_FUNC(zaxpy,ZAXPY) +#define ZCOPY_F77 F77_FUNC(zcopy,ZCOPY) +#define ZDOT_F77 F77_FUNC(zdotc,ZDOTC) +#define ZNRM2_F77 F77_FUNC(dznrm2,DZNRM2) +#define ZSCAL_F77 F77_FUNC(zscal,ZSCAL) +#define IZAMAX_F77 F77_FUNC(izamax,IZAMAX) +#define ZGEMV_F77 F77_FUNC(zgemv,ZGEMV) +#define ZGER_F77 F77_FUNC(zgerc,ZGERC) +#define ZTRMV_F77 F77_FUNC(ztrmv,ZTRMV) +#define ZGEMM_F77 F77_FUNC(zgemm,ZGEMM) +#define ZSYMM_F77 F77_FUNC(zsymm,ZSYMM) +#define ZTRMM_F77 F77_FUNC(ztrmm,ZTRMM) +#define ZTRSM_F77 F77_FUNC(ztrsm,ZTRSM) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#endif + +/* All three of these machines use a simple uppercase mangling of Fortran names */ + +/* if F77_FUNC is defined undefine it because we want to redefine */ + +#ifdef F77_FUNC +#undef F77_FUNC +#endif + + +#define F77_FUNC(lcase,UCASE) PREFIX UCASE + +#else /* Define Teuchos_fcd for all other machines */ + +#define PREFIX +#define Teuchos_fcd const char * + +/* In the future use autoconf's definition of F77_FUNC */ + +#ifndef HAVE_CONFIG_H + +#ifdef F77_FUNC +#undef F77_FUNC +#endif + +#ifdef TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE +#define F77_FUNC(lcase,UCASE) lcase +#else /* TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE not defined*/ +#define F77_FUNC(lcase,UCASE) lcase ## _ +#endif /* TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE */ + +#endif /* HAVE_CONFIG_H */ + +#define DROTG_F77 F77_FUNC(drotg,DROTG) +#define DROT_F77 F77_FUNC(drot,DROT) +#define DASUM_F77 F77_FUNC(dasum,DASUM) +#define DAXPY_F77 F77_FUNC(daxpy,DAXPY) +#define DCOPY_F77 F77_FUNC(dcopy,DCOPY) +#define DDOT_F77 F77_FUNC(ddot,DDOT) +#define DNRM2_F77 F77_FUNC(dnrm2,DNRM2) +#define DSCAL_F77 F77_FUNC(dscal,DSCAL) +#define IDAMAX_F77 F77_FUNC(idamax,IDAMAX) +#define DGEMV_F77 F77_FUNC(dgemv,DGEMV) +#define DGER_F77 F77_FUNC(dger,DGER) +#define DTRMV_F77 F77_FUNC(dtrmv,DTRMV) +#define DGEMM_F77 F77_FUNC(dgemm,DGEMM) +#define DSYMM_F77 F77_FUNC(dsymm,DSYMM) +#define DTRMM_F77 F77_FUNC(dtrmm,DTRMM) +#define DTRSM_F77 F77_FUNC(dtrsm,DTRSM) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZROTG_F77 F77_FUNC(zrotg,ZROTG) +#define ZROT_F77 F77_FUNC(zrot,ZROT) +#define ZASUM_F77 F77_FUNC(dzasum,DZASUM) +#define ZAXPY_F77 F77_FUNC(zaxpy,ZAXPY) +#define ZCOPY_F77 F77_FUNC(zcopy,ZCOPY) +#define ZDOT_F77 F77_FUNC(zdotc,ZDOTC) +#define ZNRM2_F77 F77_FUNC(dznrm2,DZNRM2) +#define ZSCAL_F77 F77_FUNC(zscal,ZSCAL) +#define IZAMAX_F77 F77_FUNC(izamax,IZAMAX) +#define ZGEMV_F77 F77_FUNC(zgemv,ZGEMV) +#define ZGER_F77 F77_FUNC(zgerc,ZGERC) +#define ZTRMV_F77 F77_FUNC(ztrmv,ZTRMV) +#define ZGEMM_F77 F77_FUNC(zgemm,ZGEMM) +#define ZSYMM_F77 F77_FUNC(zsymm,ZSYMM) +#define ZTRMM_F77 F77_FUNC(ztrmm,ZTRMM) +#define ZTRSM_F77 F77_FUNC(ztrsm,ZTRSM) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#endif + + +/* Explicitly define each F77 name for all BLAS kernels */ + +#define SROTG_F77 F77_FUNC(srotg,SROTG) +#define SROT_F77 F77_FUNC(srot,SROT) +#define SSCAL_F77 F77_FUNC(sscal,SSCAL) +#define SCOPY_F77 F77_FUNC(scopy,SCOPY) +#define SAXPY_F77 F77_FUNC(saxpy,SAXPY) +#define SDOT_F77 F77_FUNC(sdot,SDOT) +#define SNRM2_F77 F77_FUNC(snrm2,SNRM2) +#define SASUM_F77 F77_FUNC(sasum,SASUM) +#define ISAMAX_F77 F77_FUNC(isamax,ISAMAX) + +#define SGEMV_F77 F77_FUNC(sgemv,SGEMV) +#define SGER_F77 F77_FUNC(sger,SGER) +#define STRMV_F77 F77_FUNC(strmv,STRMV) +#define SGEMM_F77 F77_FUNC(sgemm,SGEMM) +#define SSYMM_F77 F77_FUNC(ssymm,SSYMM) +#define STRMM_F77 F77_FUNC(strmm,STRMM) +#define STRSM_F77 F77_FUNC(strsm,STRSM) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define CROTG_F77 F77_FUNC(crotg,CROTG) +#define CROT_F77 F77_FUNC(crot,CROT) +#define CASUM_F77 F77_FUNC(scasum,SCASUM) +#define CAXPY_F77 F77_FUNC(caxpy,CAXPY) +#define CCOPY_F77 F77_FUNC(ccopy,CCOPY) +#define CDOT_F77 F77_FUNC(cdotc,CDOTC) +#define CNRM2_F77 F77_FUNC(scnrm2,SCNRM2) +#define CSCAL_F77 F77_FUNC(cscal,CSCAL) +#define ICAMAX_F77 F77_FUNC(icamax,ICAMAX) +#define CGEMV_F77 F77_FUNC(cgemv,CGEMV) +#define CGER_F77 F77_FUNC(cgerc,CGERC) +#define CTRMV_F77 F77_FUNC(ctrmv,CTRMV) +#define CGEMM_F77 F77_FUNC(cgemm,CGEMM) +#define CSYMM_F77 F77_FUNC(csymm,CSYMM) +#define CTRMM_F77 F77_FUNC(ctrmm,CTRMM) +#define CTRSM_F77 F77_FUNC(ctrsm,CTRSM) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#ifdef __cplusplus +extern "C" { +#endif + + +/* Double precision BLAS 1 */ +void PREFIX DROTG_F77(double* da, double* db, double* c, double* s); +void PREFIX DROT_F77(const int* n, double* dx, const int* incx, double* dy, const int* incy, double* c, double* s); +double PREFIX DASUM_F77(const int* n, const double x[], const int* incx); +void PREFIX DAXPY_F77(const int* n, const double* alpha, const double x[], const int* incx, double y[], const int* incy); +void PREFIX DCOPY_F77(const int* n, const double *x, const int* incx, double *y, const int* incy); +double PREFIX DDOT_F77(const int* n, const double x[], const int* incx, const double y[], const int* incy); +double PREFIX DNRM2_F77(const int* n, const double x[], const int* incx); +void PREFIX DSCAL_F77(const int* n, const double* alpha, double *x, const int* incx); +int PREFIX IDAMAX_F77(const int* n, const double *x, const int* incx); + +/* Double std::complex precision BLAS 1 */ +#ifdef HAVE_TEUCHOS_COMPLEX + +void PREFIX ZROTG_F77(std::complex* da, std::complex* db, double* c, std::complex* s); +void PREFIX ZROT_F77(const int* n, std::complex* dx, const int* incx, std::complex* dy, const int* incy, double* c, std::complex* s); +double PREFIX ZASUM_F77(const int* n, const std::complex x[], const int* incx); +void PREFIX ZAXPY_F77(const int* n, const std::complex* alpha, const std::complex x[], const int* incx, std::complex y[], const int* incy); +void PREFIX ZCOPY_F77(const int* n, const std::complex *x, const int* incx, std::complex *y, const int* incy); +std::complex PREFIX ZDOT_F77(const int* n, const std::complex x[], const int* incx, const std::complex y[], const int* incy); +double PREFIX ZNRM2_F77(const int* n, const std::complex x[], const int* incx); +void PREFIX ZSCAL_F77(const int* n, const std::complex* alpha, std::complex *x, const int* incx); +int PREFIX IZAMAX_F77(const int* n, const std::complex *x, const int* incx); + +#endif // HAVE_TEUCHOS_COMPLEX + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +/* Single precision BLAS 1 */ +void PREFIX SROTG_F77(float* da, float* db, float* c, float* s); +void PREFIX SROT_F77(const int* n, float* dx, const int* incx, float* dy, const int* incy, float* c, float* s); +float PREFIX SASUM_F77(const int* n, const float x[], const int* incx); +void PREFIX SAXPY_F77(const int* n, const float* alpha, const float x[], const int* incx, float y[], const int* incy); +void PREFIX SCOPY_F77(const int* n, const float *x, const int* incx, float *y, const int* incy); +float PREFIX SDOT_F77(const int* n, const float x[], const int* incx, const float y[], const int* incy); +float PREFIX SNRM2_F77(const int* n, const float x[], const int* incx); +void PREFIX SSCAL_F77(const int* n, const float* alpha, float *x, const int* incx); +int PREFIX ISAMAX_F77(const int* n, const float *x, const int* incx); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +/* Single std::complex precision BLAS 1 */ +#if defined(HAVE_TEUCHOS_COMPLEX) && defined(HAVE_TEUCHOS_BLASFLOAT) + +void PREFIX CROTG_F77(std::complex* da, std::complex* db, float* c, std::complex* s); +void PREFIX CROT_F77(const int* n, std::complex* dx, const int* incx, std::complex* dy, const int* incy, float* c, std::complex* s); +float PREFIX CASUM_F77(const int* n, const std::complex x[], const int* incx); +void PREFIX CAXPY_F77(const int* n, const std::complex* alpha, const std::complex x[], const int* incx, std::complex y[], const int* incy); +void PREFIX CCOPY_F77(const int* n, const std::complex *x, const int* incx, std::complex *y, const int* incy); +std::complex PREFIX CDOT_F77(const int* n, const std::complex x[], const int* incx, const std::complex y[], const int* incy); +float PREFIX CNRM2_F77(const int* n, const std::complex x[], const int* incx); +void PREFIX CSCAL_F77(const int* n, const std::complex* alpha, std::complex *x, const int* incx); +int PREFIX ICAMAX_F77(const int* n, const std::complex *x, const int* incx); + +#endif // defined(HAVE_TEUCHOS_COMPLEX) && defined(HAVE_TEUCHOS_BLASFLOAT) + +/* Double precision BLAS 2 */ +void PREFIX DGEMV_F77(Teuchos_fcd, const int* m, const int* n, const double* alpha, const double A[], const int* lda, + const double x[], const int* incx, const double* beta, double y[], const int* incy); +void PREFIX DTRMV_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int *n, + const double *a, const int *lda, double *x, const int *incx); +void PREFIX DGER_F77(const int *m, const int *n, const double *alpha, const double *x, const int *incx, const double *y, + const int *incy, double *a, const int *lda); + +/* Double precision BLAS 2 */ +#ifdef HAVE_TEUCHOS_COMPLEX + +void PREFIX ZGEMV_F77(Teuchos_fcd, const int* m, const int* n, const std::complex* alpha, const std::complex A[], const int* lda, + const std::complex x[], const int* incx, const std::complex* beta, std::complex y[], const int* incy); +void PREFIX ZTRMV_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int *n, + const std::complex *a, const int *lda, std::complex *x, const int *incx); +void PREFIX ZGER_F77(const int *m, const int *n, const std::complex *alpha, const std::complex *x, const int *incx, const std::complex *y, + const int *incy, std::complex *a, const int *lda); + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +/* Single precision BLAS 2 */ +void PREFIX SGEMV_F77(Teuchos_fcd, const int* m, const int* n, const float* alpha, const float A[], const int* lda, + const float x[], const int* incx, const float* beta, float y[], const int* incy); +void PREFIX STRMV_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int *n, + const float *a, const int *lda, float *x, const int *incx); +void PREFIX SGER_F77(const int *m, const int *n, const float *alpha, const float *x, const int *incx, const float *y, + const int *incy, float *a, const int *lda); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +/* Single std::complex precision BLAS 2 */ +#if defined(HAVE_TEUCHOS_COMPLEX) && defined(HAVE_TEUCHOS_BLASFLOAT) + +void PREFIX CGEMV_F77(Teuchos_fcd, const int* m, const int* n, const std::complex* alpha, const std::complex A[], const int* lda, + const std::complex x[], const int* incx, const std::complex* beta, std::complex y[], const int* incy); +void PREFIX CTRMV_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int *n, + const std::complex *a, const int *lda, std::complex *x, const int *incx); +void PREFIX CGER_F77(const int *m, const int *n, const std::complex *alpha, const std::complex *x, const int *incx, const std::complex *y, + const int *incy, std::complex *a, const int *lda); + +#endif // defined(HAVE_TEUCHOS_COMPLEX) && defined(HAVE_TEUCHOS_BLASFLOAT) + +/* Double precision BLAS 3 */ +void PREFIX DGEMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * + n, const int *k, const double *alpha, const double *a, const int *lda, + const double *b, const int *ldb, const double *beta, double *c, const int *ldc); +void PREFIX DSYMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * n, + const double *alpha, const double *a, const int *lda, + const double *b, const int *ldb, const double *beta, double *c, const int *ldc); +void PREFIX DTRMM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const double *alpha, const double *a, const int * lda, double *b, const int *ldb); +void PREFIX DTRSM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const double *alpha, const double *a, const int * + lda, double *b, const int *ldb); + +/* Double std::complex precision BLAS 3 */ +#ifdef HAVE_TEUCHOS_COMPLEX + +void PREFIX ZGEMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * + n, const int *k, const std::complex *alpha, const std::complex *a, const int *lda, + const std::complex *b, const int *ldb, const std::complex *beta, std::complex *c, const int *ldc); +void PREFIX ZSYMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * n, + const std::complex *alpha, const std::complex *a, const int *lda, + const std::complex *b, const int *ldb, const std::complex *beta, std::complex *c, const int *ldc); +void PREFIX ZTRMM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const std::complex *alpha, const std::complex *a, const int * lda, std::complex *b, const int *ldb); +void PREFIX ZTRSM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const std::complex *alpha, const std::complex *a, const int * + lda, std::complex *b, const int *ldb); + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +/* Single precision BLAS 3 */ +void PREFIX SGEMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * + n, const int *k, const float *alpha, const float *a, const int *lda, + const float *b, const int *ldb, const float *beta, float *c, const int *ldc); +void PREFIX SSYMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * n, + const float *alpha, const float *a, const int *lda, + const float *b, const int *ldb, const float *beta, float *c, const int *ldc); +void PREFIX STRMM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const float *alpha, const float *a, const int * lda, float *b, const int *ldb); +void PREFIX STRSM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const float *alpha, const float *a, const int * + lda, float *b, const int *ldb); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +/* Single std::complex precision BLAS 3 */ + +#ifdef HAVE_TEUCHOS_COMPLEX + +void PREFIX CGEMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * + n, const int *k, const std::complex *alpha, const std::complex *a, const int *lda, + const std::complex *b, const int *ldb, const std::complex *beta, std::complex *c, const int *ldc); +void PREFIX CSYMM_F77(Teuchos_fcd, Teuchos_fcd, const int *m, const int * n, + const std::complex *alpha, const std::complex *a, const int *lda, + const std::complex *b, const int *ldb, const std::complex *beta, std::complex *c, const int *ldc); +void PREFIX CTRMM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const std::complex *alpha, const std::complex *a, const int * lda, std::complex *b, const int *ldb); +void PREFIX CTRSM_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, + const int *m, const int *n, const std::complex *alpha, const std::complex *a, const int * + lda, std::complex *b, const int *ldb); + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#ifdef __cplusplus +} +#endif + +#endif // end of TEUCHOS_BLAS_WRAPPERS_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_CTimeMonitor.h b/fastlib/trilinos/include/Teuchos_CTimeMonitor.h new file mode 100644 index 0000000000..a8e917e9b3 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_CTimeMonitor.h @@ -0,0 +1,83 @@ +/* @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +*/ + +#ifndef TEUCHOS_CTIMEMONITOR_H +#define TEUCHOS_CTIMEMONITOR_H + +/*! \file Teuchos_CTimeMonitor.hpp + \brief Timer functions for C that starts and stops timers for C code. +*/ + +#ifdef __cplusplus +extern "C" { +#endif + +/** \brief Start a timer with a given name and ID. + * + * \param timerName + * [in] Globally unique null-terminated string name of the timer. + * This is only significant on the first call. + * + * \param timerID + * [in] On first call, timerID should be less than + * 0 On future calls, it should be what was returned by the + * first call. + * + * \returns on first call returnVal gives the ID of a newly created + * timer of the given globally unique name timerName. On future + * calls, returnVal==timerID. + * + * \note You can not start the same timer more than once. You must stop a + * timer with Teuchos_stopTimer() before you can call this function + * to start it again. + */ +int Teuchos_startTimer( char timerName[], int timerID ); + +/** \brief Stop a timer that was started with Teuchos_startTimer(). + * + * \param timerID + * [in] Must be the ID returned from a prior call to + * Teuchos_startTimer(). + * + * + * Preconditions:
      + *
    • timerID >= 0 and it must have been + * created by a prior call to Teuchos_startTimer(). + *
    + * + * \note It is okay to stop a timer more than once (i.e. stop a timer that is + * not running). But, the timer must actually exist. + */ +void Teuchos_stopTimer( int timerID ); + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* TEUCHOS_CTIMEMONITOR_H */ diff --git a/fastlib/trilinos/include/Teuchos_Comm.hpp b/fastlib/trilinos/include/Teuchos_Comm.hpp new file mode 100644 index 0000000000..3d58131605 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Comm.hpp @@ -0,0 +1,243 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_COMM_HPP +#define TEUCHOS_COMM_HPP + +#include "Teuchos_ReductionOp.hpp" + +namespace Teuchos { + +/** \brief Abstract interface class for a basic communication channel between + * one or more processes. + * + * This interface is templated on the ordinal type but only deals with buffers + * of untyped data represented as arrays char type. All reduction + * operations that are initiated by the concreate communicator object are + * performed by user-defined ReductOpBase objects. It is the + * responsibility of the ReductOpBase object to know what the currect + * data type is, to perform casts or serializations/unserializations to and + * from char[] buffers, and to know how to reduce the objects + * correctly. It is strictly up to the client to correctly convert data types + * to char[] arrays but there is a great deal of helper code to make + * this easy and safe. + * + * ToDo: Finish documentation! + */ +template +class Comm : virtual public Describable { +public: + + //! @name Query functions + //@{ + + /** \brief Returns the rank of this process. + * + * Postconditions:
      + *
    • 0 <= return && return < this->getSize() + *
    + */ + virtual int getRank() const = 0; + + /** \brief Returns the number of processes that make up this communicator. + * + * Postconditions:
      + *
    • return > 0 + *
    + */ + virtual int getSize() const = 0; + + //@} + + //! @name Collective Operations + //@{ + + /** \brief Pause every process in *this communicator until all the + * processes reach this point. + */ + virtual void barrier() const = 0; + + /** \brief Broadcast values from the root process to the slave processes. + * + * \param rootRank + * [in] The rank of the root process. + * \param count + * [in] The number of bytes in buffer[]. + * \param buffer + * [in/out] Array (length bytes) of packed data. Must be set on input + * on the root processes with rank root. On output, each processs, + * including the root process contains the data. + * + * Preconditions:
      + *
    • 0 <= rootRank && rootRank < this->getSize() + *
    + */ + virtual void broadcast( + const int rootRank, const Ordinal bytes, char buffer[] + ) const = 0; + + /** \brief Gather values from each process to collect on all processes. + * + * \param sendBytes + * [in] Number of entires in sendBuffer[] on input. + * \param sendBuffer + * [in] Array (length sendBytes) of data being sent from each process. + * \param recvBytes + * [in] Number of entires in recvBuffer[] which must be + * equal to sendBytes*this->getSize(). This field is just here + * for debug checking. + * \param recvBuffer + * [out] Array (length recvBytes) of all of the entires + * sent from each processes. Specifically, recvBuffer[sendBytes*j+i], + * for j=0...this->getSize()-1 and i=0...sendBytes-1, + * is the entry sendBuffer[i] from process with rank j. + * + * Preconditions:
      + *
    • recvBytes==sendBytes*this->getSize() + *
    + */ + virtual void gatherAll( + const Ordinal sendBytes, const char sendBuffer[] + ,const Ordinal recvBytes, char recvBuffer[] + ) const = 0; + + /** \brief Global reduction. + * + * \param reductOp + * [in] The user-defined reduction operation + * \param bytes + * [in] The length of the buffers sendBuffer[] and globalReducts[]. + * \param sendBuffer + * [in] Array (length bytes) of the data contributed from each process. + * \param globalReducts + * [out] Array (length bytes) of the global reduction from each process. + */ + virtual void reduceAll( + const ValueTypeReductionOp &reductOp + ,const Ordinal bytes, const char sendBuffer[], char globalReducts[] + ) const = 0; + + /** \brief Global reduction combined with a scatter. + * + * \param reductOp + * [in] The user-defined reduction operation. + * \param sendBytes + * [in] The number of entires in sendBuffer[]. This must be the same + * in each process. + * \param sendBuffer + * [in] Array (length sendBytes) of the data contributed from each process. + * \param recvCounts + * [in] Array (length this->getSize()) which gives the number of element + * blocks of block size blockSize from the global reduction that will be + * recieved in each process. + * \param blockSize + * [in] Gives the block size for interpreting recvCount + * \param myGlobalReducts + * [out] Array (length blockSize*recvBytes[rank]) of the global reductions gathered + * in this process. + * + * Preconditions:
      + *
    • sendBytes == blockSize*sum(recvCounts[i],i=0...this->getSize()-1) + *
    + */ + virtual void reduceAllAndScatter( + const ValueTypeReductionOp &reductOp + ,const Ordinal sendBytes, const char sendBuffer[] + ,const Ordinal recvCounts[], const Ordinal blockSize, char myGlobalReducts[] + ) const = 0; + + /** \brief Scan reduction. + * + * \param reductOp + * [in] The user-defined reduction operation + * \param bytes + * [in] The length of the buffers sendBuffer[] and scanReducts[]. + * \param sendBuffer + * [in] Array (length bytes) of the data contributed from each process. + * \param scanReducts + * [out] Array (length bytes) of the reduction up to and including + * this process. + */ + virtual void scan( + const ValueTypeReductionOp &reductOp + ,const Ordinal bytes, const char sendBuffer[], char scanReducts[] + ) const = 0; + + //! @name Point-to-Point Operations + //@{ + + /** \brief Blocking send of data from this process to another process. + * + * \param bytes + * [in] The number of bytes of data being passed between processes. + * \param sendBuffer + * [in] Array (length bytes) of data being sent from this process. + * This buffer can be immediately destroyed or reused as soon as the function + * exits (that is why this function is "blocking"). + * \param destRank + * [in] The rank of the process to recieve the data. + * + * Preconditions:
      + *
    • 0 <= destRank && destRank < this->getSize() + *
    • destRank != this->getRank() + *
    + */ + virtual void send( + const Ordinal bytes, const char sendBuffer[], const int destRank + ) const = 0; + + /** \brief Blocking receive of data from this process to another process. + * + * \param sourceRank + * [in] The rank of the process to recieve the data from. If sourceRank < 0 then + * data will be recieved from any process. + * \param bytes + * [in] The number of bytes of data being passed between processes. + * \param recvBuffer + * [out] Array (length bytes) of data being received from this process. + * This buffer can be immediately used to access the data as soon as the function + * exits (that is why this function is "blocking"). + * + * Preconditions:
      + *
    • [sourceRank >= 0] sourceRank < this->getSize() + *
    • sourceRank != this->getRank() + *
    + * + * \return Returns the senders rank. + */ + virtual int receive( + const int sourceRank, const Ordinal bytes, char recvBuffer[] + ) const = 0; + + //@} + +}; // class Comm + +} // namespace Teuchos + +#endif // TEUCHOS_COMM_HPP diff --git a/fastlib/trilinos/include/Teuchos_CommHelpers.hpp b/fastlib/trilinos/include/Teuchos_CommHelpers.hpp new file mode 100644 index 0000000000..4cfb33e81e --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_CommHelpers.hpp @@ -0,0 +1,1003 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_COMM_HELPERS_HPP +#define TEUCHOS_COMM_HELPERS_HPP + +#include "Teuchos_Comm.hpp" +#include "Teuchos_CommUtilities.hpp" +#include "Teuchos_SerializationTraitsHelpers.hpp" +#include "Teuchos_ReductionOpHelpers.hpp" +#include "Teuchos_SerializerHelpers.hpp" +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_OrdinalTraits.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_TypeNameTraits.hpp" + +namespace Teuchos { + +// +// Teuchos::Comm Helper Functions +// + +/** \brief Enumeration for selecting from a set of pre-defined reduction + * operations. + * + * \relates Comm + */ +enum EReductionType { + REDUCE_SUM ///< Sum + ,REDUCE_MIN ///< Min + ,REDUCE_MAX ///< Max + ,REDUCE_AND ///< Logical AND +}; + +/** \brief Convert to std::string representation. + * + * \relates EReductionType + */ +inline +const char* toString( const EReductionType reductType ) +{ + switch(reductType) { + case REDUCE_SUM: return "REDUCE_SUM"; + case REDUCE_MIN: return "REDUCE_MIN"; + case REDUCE_MAX: return "REDUCE_MAX"; + case REDUCE_AND: return "REDUCE_AND"; + default: TEST_FOR_EXCEPT(true); + } + return 0; // Will never be called +} + +/** \brief Get the process rank. + * + * \relates Comm + */ +template +int rank(const Comm& comm); + +/** \brief Get the number of processes in the communicator. + * + * \relates Comm + */ +template +int size(const Comm& comm); + +/** \brief Barrier. + * + * \relates Comm + */ +template +void barrier(const Comm& comm); + +/** \brief Broadcast array of objects that use value semantics. + * + * \relates Comm + */ +template +void broadcast( + const Comm& comm + ,const int rootRank, const Ordinal count, Packet buffer[] + ); + +/** \brief Broadcast single object that use value semantics. + * + * \relates Comm + */ +template +void broadcast( + const Comm& comm + ,const int rootRank, Packet *object + ); + +/** \brief Broadcast array of objects that use reference semantics. + * + * \relates Comm + */ +template +void broadcast( + const Comm& comm, const Serializer &serializer + ,const int rootRank, const Ordinal count, Packet*const buffer[] + ); + +/** \brief Gather array of objects that use value semantics from every process + * to every process. + * + * \relates Comm + */ +template +void gatherAll( + const Comm& comm + ,const Ordinal sendCount, const Packet sendBuffer[] + ,const Ordinal recvCount, Packet recvBuffer[] + ); + +/** \brief Gather array of objects that use reference semantics from every + * process to every process. + * + * \relates Comm + */ +template +void gatherAll( + const Comm& comm, const Serializer &serializer + ,const Ordinal sendCount, const Packet*const sendBuffer[] + ,const Ordinal recvCount, Packet*const recvBuffer[] + ); + +/** \brief Collective reduce all of array of objects using value semantics + * using a user-defined reduction operator. + * + * \relates Comm + */ +template +void reduceAll( + const Comm& comm, const ValueTypeReductionOp &reductOp + ,const Ordinal count, const Packet sendBuffer[], Packet globalReducts[] + ); + +/** \brief Collective reduce all of array of objects using value semantics + * using a pre-defined reduction type. + * + * \relates Comm + */ +template +void reduceAll( + const Comm& comm, const EReductionType reductType + ,const Ordinal count, const Packet sendBuffer[], Packet globalReducts[] + ); + +/** \brief Collective reduce all for single object using value semantics using + * a pre-defined reduction type. + * + * \relates Comm + */ +template +void reduceAll( + const Comm& comm, const EReductionType reductType + ,const Packet &send, Packet *globalReduct + ); + +/** \brief Collective reduce all for array of objects using reference + * semantics. + * + * \relates Comm + */ +template +void reduceAll( + const Comm& comm, const Serializer &serializer + ,const ReferenceTypeReductionOp &reductOp + ,const Ordinal count, const Packet*const sendBuffer[], Packet*const globalReducts[] + ); + +/** \brief Reduce and Scatter array of objects that use value semantics using + * a user-defined reduction object. + * + * \relates Comm + */ +template +void reduceAllAndScatter( + const Comm& comm, const ValueTypeReductionOp &reductOp + ,const Ordinal sendCount, const Packet sendBuffer[] + ,const Ordinal recvCounts[], Packet myGlobalReducts[] + ); + +/** \brief Reduce and Scatter array of objects that use value semantics using + * a a pre-defined reduction type. + * + * \relates Comm + */ +template +void reduceAllAndScatter( + const Comm& comm, const EReductionType reductType + ,const Ordinal sendCount, const Packet sendBuffer[] + ,const Ordinal recvCounts[], Packet myGlobalReducts[] + ); + +/** \brief Reduce and Scatter array of objects that use reference semantics + * using a user-defined reduction object. + * + * \relates Comm + */ +template +void reduceAllAndScatter( + const Comm& comm, const Serializer &serializer + ,const ReferenceTypeReductionOp &reductOp + ,const Ordinal sendCount, const Packet*const sendBuffer[] + ,const Ordinal recvCounts[], Packet*const myGlobalReducts[] + ); + +/** \brief Scan/Reduce array of objects that use value semantics using a + * user-defined reduction operator. + * + * \relates Comm + */ +template +void scan( + const Comm& comm, const ValueTypeReductionOp &reductOp + ,const Ordinal count, const Packet sendBuffer[], Packet scanReducts[] + ); + +/** \brief Scan/Reduce array of objects using value semantics using a + * predefined reduction type. + * + * \relates Comm + */ +template +void scan( + const Comm& comm, const EReductionType reductType + ,const Ordinal count, const Packet sendBuffer[], Packet scanReducts[] + ); + +/** \brief Scan/Reduce single object using value semantics using a predefined + * reduction type. + * + * \relates Comm + */ +template +void scan( + const Comm& comm, const EReductionType reductType + ,const Packet &send, Packet *scanReduct + ); + +/** \brief Scan/Reduce array of objects that use reference semantics using a + * user-defined reduction operator. + * + * \relates Comm + */ +template +void scan( + const Comm& comm, const Serializer &serializer + ,const ReferenceTypeReductionOp &reductOp + ,const Ordinal count, const Packet*const sendBuffer[], Packet*const scanReducts[] + ); + +/** \brief Send objects that use values semantics to another process. + * + * \relates Comm + */ +template +void send( + const Comm& comm + ,const Ordinal count, const Packet sendBuffer[], const int destRank + ); + +/** \brief Send a single object that use values semantics to another process. + * + * \relates Comm + */ +template +void send( + const Comm& comm + ,const Packet &send, const int destRank + ); + +/** \brief Send objects that use reference semantics to another process. + * + * \relates Comm + */ +template +void send( + const Comm& comm, const Serializer &serializer + ,const Ordinal count, const Packet*const sendBuffer[], const int destRank + ); + +/** \brief Receive objects that use values semantics from another process. + * + * \relates Comm + */ +template +int receive( + const Comm& comm + ,const int sourceRank, const Ordinal count, Packet recvBuffer[] + ); + +/** \brief Receive a single object that use values semantics from another process. + * + * \relates Comm + */ +template +int receive( + const Comm& comm + ,const int sourceRank, Packet *recv + ); + +/** \brief Receive objects that use reference semantics from another process. + * + * \relates Comm + */ +template +int receive( + const Comm& comm, const Serializer &serializer + ,const int sourceRank, const Ordinal count, Packet*const recvBuffer[] + ); + +// +// Standard reduction subclasses for objects that use value semantics +// + +/** \brief Standard summation operator for types with value semantics. + * + * \relates Comm + */ +template +class SumValueReductionOp : public ValueTypeReductionOp +{ +public: + /** \brief . */ + void reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const; +}; + +/** \brief Standard min operator for types with value semantics. + * + * Note, this class object will throw an std::exception when used with a packet + * type where ScalarTraits::isComparable==false but it will + * still compile. + * + * \relates Comm + */ +template +class MinValueReductionOp : public ValueTypeReductionOp +{ +public: + /** \brief . */ + void reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const; +}; + +/** \brief Standard Max operator for types with value semantics. + * + * Note, this class object will throw an std::exception when used with a packet + * type where ScalarTraits::isComparable==false but it will + * still compile. + * + * \relates Comm + */ +template +class MaxValueReductionOp : public ValueTypeReductionOp +{ +public: + /** \brief . */ + void reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const; +}; + + + +/** \brief Standard logical AND operator for booleans + * + * \relates Comm + */ +template +class ANDValueReductionOp : public ValueTypeReductionOp +{ +public: + /** \brief . */ + void reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const; +}; + + + + + +// //////////////////////////////////////////////////////////// +// Implementation details (not for geneal users to mess with) + +// +// ReductionOp Utilities +// + +namespace MixMaxUtilities { + +template +class Min {}; + +template +class Min { +public: + static void min( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) + { + for( int i = 0; i < count; ++i ) + inoutBuffer[i] = TEUCHOS_MIN(inoutBuffer[i],inBuffer[i]); + } +}; + +template +class Min { +public: + static void min( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) + { + TEST_FOR_EXCEPTION( + true,std::logic_error + ,"Error, the type "<::name() + <<" does not support comparison operations!" + ); + } +}; + +template +class Max {}; + +template +class Max { +public: + static void max( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) + { + for( int i = 0; i < count; ++i ) + inoutBuffer[i] = TEUCHOS_MAX(inoutBuffer[i],inBuffer[i]); + } +}; + +template +class Max { +public: + static void max( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) + { + TEST_FOR_EXCEPTION( + true,std::logic_error + ,"Error, the type "<::name() + <<" does not support comparison operations!" + ); + } +}; + +template +class AND {}; + +template +class AND { +public: + static void And( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) + { + for( int i = 0; i < count; ++i ) + inoutBuffer[i] = inoutBuffer[i] && inBuffer[i]; + } +}; + +template +class AND { +public: + static void And( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) + { + TEST_FOR_EXCEPTION( + true,std::logic_error + ,"Error, the type "<::name() + <<" does not support logical AND operations!" + ); + } +}; + +} // namespace MixMaxUtilities + +template +void SumValueReductionOp::reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const +{ + for( int i = 0; i < count; ++i ) + inoutBuffer[i] += inBuffer[i]; +} + +template +void MinValueReductionOp::reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const +{ + typedef ScalarTraits ST; + MixMaxUtilities::Min::min( + count,inBuffer,inoutBuffer + ); +} + +template +void MaxValueReductionOp::reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const +{ + typedef ScalarTraits ST; + MixMaxUtilities::Max::max( + count,inBuffer,inoutBuffer + ); +} + +template +void ANDValueReductionOp::reduce( + const Ordinal count + ,const Packet inBuffer[] + ,Packet inoutBuffer[] + ) const +{ + typedef ScalarTraits ST; + MixMaxUtilities::AND::And( + count,inBuffer,inoutBuffer + ); +} + +} // namespace Teuchos + +// ////////////////////////// +// Template implemenations + +// +// ReductionOp utilities +// + +namespace Teuchos { + + +// Not for the general user to use! I am returning a raw ReducionOp* pointer +// to avoid the overhead of using RCP. However, given the use case +// this is just fine since I can just use std::auto_ptr to make sure things +// are deleted correctly. +template +ValueTypeReductionOp* createOp( const EReductionType reductType ) +{ + typedef ScalarTraits ST; + switch(reductType) { + case REDUCE_SUM: { + return new SumValueReductionOp(); + break; + } + case REDUCE_MIN: { + TEST_FOR_EXCEPT(!ST::isComparable); + return new MinValueReductionOp(); + break; + } + case REDUCE_MAX: { + TEST_FOR_EXCEPT(!ST::isComparable); + return new MaxValueReductionOp(); + break; + } + case REDUCE_AND: { + return new ANDValueReductionOp(); + break; + } + default: + TEST_FOR_EXCEPT(true); + } + return 0; // Will never be called! +} + +} // namespace Teuchos + +// +// Teuchos::Comm wrapper functions +// + +template +int Teuchos::rank(const Comm& comm) +{ + return comm.getRank(); +} + +template +int Teuchos::size(const Comm& comm) +{ + return comm.getSize(); +} + +template +void Teuchos::barrier(const Comm& comm) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: barrier<" + <::name() + <<">()" + ); + comm.barrier(); +} + +template +void Teuchos::broadcast( + const Comm& comm + ,const int rootRank, const Ordinal count, Packet buffer[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: broadcast<" + <::name()<<","<::name() + <<">( value type )" + ); + ValueTypeSerializationBuffer + charBuffer(count,buffer); + comm.broadcast( + rootRank,charBuffer.getBytes(),charBuffer.getCharBuffer() + ); +} + +template +void Teuchos::broadcast( + const Comm& comm + ,const int rootRank, Packet *object + ) +{ + broadcast(comm,rootRank,1,object); +} + +template +void Teuchos::broadcast( + const Comm& comm, const Serializer &serializer + ,const int rootRank, const Ordinal count, Packet*const buffer[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: broadcast<" + <::name()<<","<::name() + <<">( reference type )" + ); + ReferenceTypeSerializationBuffer + charBuffer(serializer,count,buffer); + comm.broadcast( + rootRank,charBuffer.getBytes(),charBuffer.getCharBuffer() + ); +} + +template +void Teuchos::gatherAll( + const Comm& comm + ,const Ordinal sendCount, const Packet sendBuffer[] + ,const Ordinal recvCount, Packet recvBuffer[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: gatherAll<" + <::name()<<","<::name() + <<">( value type )" + ); + ConstValueTypeSerializationBuffer + charSendBuffer(sendCount,sendBuffer); + ValueTypeSerializationBuffer + charRecvBuffer(recvCount,recvBuffer); + comm.gatherAll( + charSendBuffer.getBytes(),charSendBuffer.getCharBuffer() + ,charRecvBuffer.getBytes(),charRecvBuffer.getCharBuffer() + ); +} + +template +void Teuchos::gatherAll( + const Comm& comm, const Serializer &serializer + ,const Ordinal sendCount, const Packet*const sendBuffer[] + ,const Ordinal recvCount, Packet*const recvBuffer[] + ) +{ + TEST_FOR_EXCEPT(true); // ToDo: Implement and test when needed! +} + +template +void Teuchos::reduceAll( + const Comm& comm, const ValueTypeReductionOp &reductOp + ,const Ordinal count, const Packet sendBuffer[], Packet globalReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: reduceAll<" + <::name()<<","<::name() + <<">( value type, user-defined op )" + ); + ConstValueTypeSerializationBuffer + charSendBuffer(count,sendBuffer); + ValueTypeSerializationBuffer + charGlobalReducts(count,globalReducts); + CharToValueTypeReductionOp + _reductOp(rcp(&reductOp,false)); + comm.reduceAll( + _reductOp,charSendBuffer.getBytes(),charSendBuffer.getCharBuffer() + ,charGlobalReducts.getCharBuffer() + ); +} + +template +void Teuchos::reduceAll( + const Comm& comm, const EReductionType reductType + ,const Ordinal count, const Packet sendBuffer[], Packet globalReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: reduceAll<" + <::name()<<","<::name() + <<">( value type, "< > + reductOp(createOp(reductType)); + reduceAll(comm,*reductOp,count,sendBuffer,globalReducts); +} + +template +void Teuchos::reduceAll( + const Comm& comm, const EReductionType reductType + ,const Packet &send, Packet *globalReduct + ) +{ + reduceAll(comm,reductType,1,&send,globalReduct); +} + +template +void Teuchos::reduceAll( + const Comm& comm, const Serializer &serializer + ,const ReferenceTypeReductionOp &reductOp + ,const Ordinal count, const Packet*const sendBuffer[], Packet*const globalReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: reduceAll<" + <::name()<<","<::name() + <<">( reference type )" + ); + ConstReferenceTypeSerializationBuffer + charSendBuffer(serializer,count,sendBuffer); + ReferenceTypeSerializationBuffer + charGlobalReducts(serializer,count,globalReducts); + CharToReferenceTypeReductionOp + _reductOp(rcp(&serializer,false),rcp(&reductOp,false)); + comm.reduceAll( + _reductOp,charSendBuffer.getBytes(),charSendBuffer.getCharBuffer() + ,charGlobalReducts.getCharBuffer() + ); +} + +template +void Teuchos::reduceAllAndScatter( + const Comm& comm, const ValueTypeReductionOp &reductOp + ,const Ordinal sendCount, const Packet sendBuffer[] + ,const Ordinal recvCounts[], Packet myGlobalReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: reduceAllAndScatter<" + <::name()<<","<::name() + <<">( value type, user-defined op )" + ); +#ifdef TEUCHOS_DEBUG + Ordinal sumRecvCounts = 0; + const int size = Teuchos::size(comm); + for( Ordinal i = 0; i < size; ++i ) + sumRecvCounts += recvCounts[i]; + TEST_FOR_EXCEPT(!(sumRecvCounts==sendCount)); +#endif + const int rank = Teuchos::rank(comm); + ConstValueTypeSerializationBuffer + charSendBuffer(sendCount,sendBuffer); + ValueTypeSerializationBuffer + charMyGlobalReducts(recvCounts[rank],myGlobalReducts); + CharToValueTypeReductionOp + _reductOp(rcp(&reductOp,false)); + const Ordinal + blockSize = charSendBuffer.getBytes()/sendCount; + comm.reduceAllAndScatter( + _reductOp,charSendBuffer.getBytes(),charSendBuffer.getCharBuffer() + ,recvCounts,blockSize,charMyGlobalReducts.getCharBuffer() + ); +} + +template +void Teuchos::reduceAllAndScatter( + const Comm& comm, const EReductionType reductType + ,const Ordinal sendCount, const Packet sendBuffer[] + ,const Ordinal recvCounts[], Packet myGlobalReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: reduceAllAndScatter<" + <::name()<<","<::name() + <<">( value type, "< > + reductOp(createOp(reductType)); + reduceAllAndScatter( + comm,*reductOp,sendCount,sendBuffer,recvCounts,myGlobalReducts + ); +} + +template +void Teuchos::reduceAllAndScatter( + const Comm& comm, const Serializer &serializer + ,const ReferenceTypeReductionOp &reductOp + ,const Ordinal sendCount, const Packet*const sendBuffer[] + ,const Ordinal recvCounts[], Packet*const myGlobalReducts[] + ) +{ + TEST_FOR_EXCEPT(true); // ToDo: Implement and test when needed! +} + +template +void Teuchos::scan( + const Comm& comm, const ValueTypeReductionOp &reductOp + ,const Ordinal count, const Packet sendBuffer[], Packet scanReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: scan<" + <::name()<<","<::name() + <<">( value type, user-defined op )" + ); + ConstValueTypeSerializationBuffer + charSendBuffer(count,sendBuffer); + ValueTypeSerializationBuffer + charScanReducts(count,scanReducts); + CharToValueTypeReductionOp + _reductOp(rcp(&reductOp,false)); + comm.scan( + _reductOp,charSendBuffer.getBytes(),charSendBuffer.getCharBuffer() + ,charScanReducts.getCharBuffer() + ); +} + +template +void Teuchos::scan( + const Comm& comm, const EReductionType reductType + ,const Ordinal count, const Packet sendBuffer[], Packet scanReducts[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: scan<" + <::name()<<","<::name() + <<">( value type, "< > + reductOp(createOp(reductType)); + scan(comm,*reductOp,count,sendBuffer,scanReducts); +} + +template +void Teuchos::scan( + const Comm& comm, const EReductionType reductType + ,const Packet &send, Packet *globalReduct + ) +{ + scan(comm,reductType,1,&send,globalReduct); +} + +template +void Teuchos::scan( + const Comm& comm, const Serializer &serializer + ,const ReferenceTypeReductionOp &reductOp + ,const Ordinal count, const Packet*const sendBuffer[], Packet*const scanReducts[] + ) +{ + TEST_FOR_EXCEPT(true); // ToDo: Implement and test when needed! +} + +template +void Teuchos::send( + const Comm& comm + ,const Ordinal count, const Packet sendBuffer[], const int destRank + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: send<" + <::name()<<","<::name() + <<">( value type )" + ); + ConstValueTypeSerializationBuffer + charSendBuffer(count,sendBuffer); + comm.send( + charSendBuffer.getBytes(),charSendBuffer.getCharBuffer() + ,destRank + ); +} + +template +void Teuchos::send( + const Comm& comm + ,const Packet &send, const int destRank + ) +{ + Teuchos::send(comm,1,&send,destRank); +} + +template +void Teuchos::send( + const Comm& comm, const Serializer &serializer + ,const Ordinal count, const Packet*const sendBuffer[], const int destRank + ) +{ + TEST_FOR_EXCEPT(true); // ToDo: Implement and test when needed! +} + +template +int Teuchos::receive( + const Comm& comm + ,const int sourceRank, const Ordinal count, Packet recvBuffer[] + ) +{ + TEUCHOS_COMM_TIME_MONITOR( + "Teuchos::CommHelpers: receive<" + <::name()<<","<::name() + <<">( value type )" + ); + ValueTypeSerializationBuffer + charRecvBuffer(count,recvBuffer); + return comm.receive( + sourceRank + ,charRecvBuffer.getBytes(),charRecvBuffer.getCharBuffer() + ); +} + +template +int Teuchos::receive( + const Comm& comm + ,const int sourceRank, Packet *recv + ) +{ + return Teuchos::receive(comm,sourceRank,1,recv); +} + +template +int Teuchos::receive( + const Comm& comm, const Serializer &serializer + ,const int sourceRank, const Ordinal count, Packet*const recvBuffer[] + ) +{ + TEST_FOR_EXCEPT(true); // ToDo: Implement and test when needed! +} + +#endif // TEUCHOS_COMM_HELPERS_HPP diff --git a/fastlib/trilinos/include/Teuchos_CommUtilities.hpp b/fastlib/trilinos/include/Teuchos_CommUtilities.hpp new file mode 100644 index 0000000000..73e3c824ac --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_CommUtilities.hpp @@ -0,0 +1,45 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_COMM_UTILTIES_HPP +#define TEUCHOS_COMM_UTILTIES_HPP + +#include "Teuchos_TimeMonitor.hpp" + +#ifdef HAVE_TEUCHOS_COMM_TIMERS + +#define TEUCHOS_COMM_TIME_MONITOR( FUNCNAME ) \ + TEUCHOS_FUNC_TIME_MONITOR( FUNCNAME ) + +#else // HAVE_TEUCHOS_COMM_TIMERS + +#define TEUCHOS_COMM_TIME_MONITOR( FUNCNAME ) + +#endif // HAVE_TEUCHOS_COMM_TIMERS + +#endif // TEUCHOS_COMM_UTILTIES_HPP diff --git a/fastlib/trilinos/include/Teuchos_CommandLineProcessor.hpp b/fastlib/trilinos/include/Teuchos_CommandLineProcessor.hpp new file mode 100644 index 0000000000..77dc4339f6 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_CommandLineProcessor.hpp @@ -0,0 +1,606 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_COMMAND_LINE_PROCESSOR_HPP +#define TEUCHOS_COMMAND_LINE_PROCESSOR_HPP + +/** \example CommandLineProcessor/cxx_main.cpp + This is an example of how to use the Teuchos::CommandLineProcessor class. +*/ + +/*! \file Teuchos_CommandLineProcessor.hpp + \brief Basic command line parser for input from (argc,argv[]) +*/ + +#include "Teuchos_map.hpp" +#include "Teuchos_any.hpp" +#include "Teuchos_CompileTimeAssert.hpp" + +namespace Teuchos { + +/* ToDo: RAB: 2003/10/02: Add support for required options as per KRL's suggestion + * + * ToDo: Finish documentation. + */ + +/** \brief Class that helps parse command line input arguments from + * (argc,argv[]) and set options. + * + * This class will process command-line arguments in the form of (argc,argv[]) + * and set user-defined options. This class can also work in a number of modes. + * This processor can require that all options be recognized or not. + * + * This class object will also setup the behavior of + * Teuchos::VerboseObjectBase::getDefaultOStream() if + * this->addOutputSetupOptions()==true + * + */ +class CommandLineProcessor { +public: + + //! @name Public types + //@{ + + /// Thrown if a parse std::exception occurs and throwExceptions==true + class ParseError : public std::logic_error + {public: ParseError(const std::string& what_arg) : std::logic_error(what_arg) {}}; + + /// Thrown if --help was specified and throwExceptions==true + class HelpPrinted : public ParseError + {public: HelpPrinted(const std::string& what_arg) : ParseError(what_arg) {}}; + + /// Thrown if an unrecognized option was found and throwExceptions==true + class UnrecognizedOption : public ParseError + {public: UnrecognizedOption(const std::string& what_arg) : ParseError(what_arg) {}}; + + /** \brief Return value for CommandLineProcessor::parse(). + Note: These enums are all given non-negative values since they are designed to + be returned from main(). + */ + enum EParseCommandLineReturn { + PARSE_SUCCESSFUL = 0 /*!< Parsing the command line was successful. */ + ,PARSE_HELP_PRINTED = 1 /*!< The help statement was printed for the command line parser. */ + ,PARSE_UNRECOGNIZED_OPTION = 2 /*!< The command line parser encountered an unrecognized option. */ + }; + + //@} + + //! @name Constructors + //@{ + + /** \brief Default Constructor + * + * \param throwExceptions + * [in] If true then this->parse() with throw + * exceptions instead of returning !=PARSE_SUCCESSFUL. + * \param recogniseAllOptions + * [in] If true then this->parse() with simply + * ignore options that it does not recognize. + * \param addOutputSetupOptions + * [in] If true then options will be automatically added + * to setup Teuchos::VerboseObjectBase::getDefaultOStream(). + */ + CommandLineProcessor( + bool throwExceptions = true + ,bool recogniseAllOptions = true + ,bool addOutputSetupOptions = false + ); + + //@} + + //! @name Behavior modes + //@{ + + /// Set if an std::exception is thrown, there is a parse error, or help is printed. + void throwExceptions( const bool & throwExceptions ); + + /// Returns true if an std::exception is thrown, there is a parse error, or help is printed. + bool throwExceptions() const; + + /// Set if all options must be recognized or not. + void recogniseAllOptions( const bool & recogniseAllOptions ); + + /// Returns true if all options are being recognized by the parser. + bool recogniseAllOptions() const; + + /// Set if options will be automatically added to setup Teuchos::VerboseObjectBase::getDefaultOStream(). + void addOutputSetupOptions( const bool &addOutputSetupOptions ); + + /// Returns true options will be automatically added to setup Teuchos::VerboseObjectBase::getDefaultOStream(). + bool addOutputSetupOptions() const; + + //@} + + //! @name Set up options + //@{ + + /** \brief Set a documentation sting for the entire program printed when + * --help is specified. */ + void setDocString( const char doc_string[] ); + + /** \brief Set a boolean option. + * + * \param option_true [in] (null terminated std::string) If this option is found then + * *option_val = true will be set. + * \param option_false [in] (null terminated std::string) If this option is found then + * *option_val = false will be set. + * \param option_val [in/out] On input, *option_val gives the default value + * of the option (used for printing in --help). On output, + * will be set according to (argc,argv[]). + * \param documentation [in] If !=NULL, then this null terminated std::string + * gives the documentation for the option. + */ + void setOption( + const char option_true[] + ,const char option_false[] + ,bool *option_val + ,const char documentation[] = NULL + ); + + /** \brief Set an integer option. + * + * \param option_name [in] (null terminated std::string) The name of the option + * (without the leading '--' or trailing '='). + * \param option_val [in/out] On input, *option_val gives the default value + * of the option (used for printing in --help). On output, + * will be set according to (argc,argv[]). + * \param documentation [in] If !=NULL, then this null terminated std::string + * gives the documentation for the option. + */ + void setOption( + const char option_name[] + ,int *option_val + ,const char documentation[] = NULL + ,const bool required = false + ); + + /** \brief Set a floating-point option. + * + * \param option_name [in] (null terminated std::string) The name of the option + * (without the leading '--' or trailing '='). + * \param option_val [in/out] On input, *option_val gives the default value + * of the option (used for printing in --help). On output, + * will be set according to (argc,argv[]). + * \param documentation [in] If !=NULL, then this null terminated std::string + * gives the documentation for the option. + */ + void setOption( + const char option_name[] + ,double *option_val + ,const char documentation[] = NULL + ,const bool required = false + ); + + /** \brief Set a std::string option. + * + * \param option_name [in] (null terminated std::string) The name of the option + * (without the leading '--' or trailing '='). + * \param option_val [in/out] On input, *option_val gives the default value + * of the option (used for printing in --help). On output, + * will be set according to (argc,argv[]). + * \param documentation [in] If !=NULL, then this null terminated std::string + * gives the documentation for the option. + */ + void setOption( + const char option_name[] + ,std::string *option_val + ,const char documentation[] = NULL + ,const bool required = false + ); + + /** \brief Set an enumeration option (templated by enumeration type). + * + * \param enum_option_name + * [in] (null terminated std::string) The name of the option + * (without the leading '--' or trailing '='). + * \param enum_option_val + * [in/out] On input, *enum_option_val give the default + * value of the enumeration (used for printing in --help). + * After parse() finished executing successfully, + * *enum_option_val will contain the user-selected + * value of the enumeration. + * \param num_enum_opt_values + * [in] Gives the number of possible option values to select + * \param enum_opt_values + * [in] Array (length num_enum_opt_values)) that gives + * the numeric values for each option. The values in this + * array are used to set the actual option *enum_option_val. + * \param enum_opt_names + * [in] Array (length num_enum_opt_values)) that gives + * the std::string names for each option. The strings in this function + * are what is used in the commandline. + * \param documentation + * [in] If !=NULL, then this null terminated std::string + * gives the documentation for the option. + * + * Warning! Only use enumeration or int for EType. + * Using any other type for EType could be trouble! + */ + template + void setOption( + const char enum_option_name[] + ,EType *enum_option_val + ,const int num_enum_opt_values + ,const EType enum_opt_values[] + ,const char* enum_opt_names[] + ,const char documentation[] = NULL + ,const bool required = false + ); + + //@} + + //! @name Parse + //@{ + + /** \brief Parse a command line. + * + * \param argc [in] number of entries in argv[] + * \param argv [in/out] array (length argc) of command line arguments. + * argv[0] should be the name of the program on the shell as usual. + * \param errout [out] If !=NULL then error and help messages are sent here. + * The default is set to &std::cerr. + * + * Postconditions: + *
      + *
    • If an unrecognized option is found + *
        + *
      • If this->recogniseAllOptions()==true + *
          + *
        • An error message will be printed to *errout and parsing will stop as follows: + *
        • If this->throwExceptions()==true + *
          • This method will throw an UnrecognizedOption std::exception
          + *
        • else + *
          • This method will return PARSE_UNRECOGNIZED_OPTION
          + *
        • endif + *
        + *
      • else + *
        • A warning message will be printed to *errout and parsing will continue
        + *
      • endif + *
      + *
    • else if the option --help is found + *
        + *
      • If this->throwExceptions()==true + *
        • This method will throw a HelpPrinted std::exception
        + *
      • else + *
        • This method will return PARSE_HELP_PRINTED
        + *
      • endif + *
      + *
    • else + *
      • This method will return PARSE_SUCCESSFUL
      + *
    • endif + *
    + * + * Note that if the option --pause-for-debugging is + * present, then std::string Type 0 and press enter to continue + * : will be printed to standard error (std::cerr) and + * execution will be suspended until the user enters any non-null + * character(s). This option is designed to make it easier to + * attach a debugger, especially in a parallel MPI program. If + * HAVE_MPI is defined, then output/input is only performed with the + * process with rank 0 and then MPI calls insure that all processors + * wait (using MPI_Barrier(MPI_COMM_WORLD)) until the user + * has entered something. This allows the user to attach a debugger + * to one or more parallel MPI processes and set breakpoints before + * execution resumes. Note that the stream *errout is not + * used for this output/input but instead std::cerr is + * directly used. + * + * If Teuchos::VerboseObjectBase::getDefaultOStream().get()!=NULL + * and this->addOutputSetupOptions(), then any of the default setup + * options for Teuchos::VerboseObjectBase::getDefaultOStream() that + * are set on the commandline will be set on + * Teuchos::VerboseObjectBase::getDefaultOStream(). + */ + EParseCommandLineReturn parse( + int argc + ,char* argv[] + ,std::ostream *errout = &std::cerr + ) const; + + //@} + + //! @name Miscellaneous + //@{ + + /** \brief Print the help message. + * + * \param out [in/out] The stream the documentation will be printed to. + * + * This will print a formatted set of documentation that shows what + * options are set, what their default values are and any + * user-supplied documentation about each option. + */ + void printHelpMessage( const char program_name[], std::ostream &out ) const; + + //@} + +public: + // + enum EOptType { OPT_NONE, OPT_BOOL_TRUE, OPT_BOOL_FALSE, OPT_INT, OPT_DOUBLE, OPT_STRING, OPT_ENUM_INT }; + // RAB: 2003/10/10: Note: I had to move this out of the private section since + // the sun compiler (version 7) complained (rightly it now appears after looking + // up what the ISO/ANSI C++ standard says) about the declaration for opt_val_val_t + // not being able to access a private member of CommandLineProcessor. + +private: + + // ///////////////////////////////// + // Private types + + // ToDo: RAB: 2004/05/25: Clean up these data structures and add + // support for a templated enum type. This will clean up usage + // quite a bit. + + // + struct opt_val_val_t { + opt_val_val_t() + :opt_type(OPT_NONE) + {} + opt_val_val_t( EOptType opt_type_in, const any& opt_val_in, bool required_in ) + :opt_type(opt_type_in),opt_val(opt_val_in),required(required_in),was_read(false) + {} + EOptType opt_type; + any opt_val; // Will be bool*, int*, double*, std::string* or a small int (for OPT_ENUM_INT) + bool required; + bool was_read; + }; + + // + typedef Teuchos::map options_list_t; + + // + struct opt_doc_t { + opt_doc_t() + :opt_type(OPT_NONE) + {} + opt_doc_t(EOptType opt_type_in, const std::string& opt_name_in, const std::string& opt_name_false_in + ,const std::string &documentation_in, const any &default_val_in ) + :opt_type(opt_type_in),opt_name(opt_name_in),opt_name_false(opt_name_false_in) + ,documentation(documentation_in),default_val(default_val_in) + {} + EOptType opt_type; + std::string opt_name; + std::string opt_name_false; // only for bool + std::string documentation; + any default_val; + }; + + // + typedef std::vector options_documentation_list_t; + + // + struct enum_opt_data_t { + enum_opt_data_t() + :enum_option_val(NULL), num_enum_opt_values(0) + {} + enum_opt_data_t( + int *_enum_option_val + ,const int _num_enum_opt_values + ,const int _enum_opt_values[] + ,const char* _enum_opt_names[] + ) + :enum_option_val(_enum_option_val) + ,num_enum_opt_values(_num_enum_opt_values) + ,enum_opt_values(_enum_opt_values,_enum_opt_values+_num_enum_opt_values) + { + for( int k = 0; k < num_enum_opt_values; ++k ) + enum_opt_names.push_back(std::string(_enum_opt_names[k])); + } + int *enum_option_val; + int num_enum_opt_values; + std::vector enum_opt_values; + std::vector enum_opt_names; + }; + + // + typedef std::vector enum_opt_data_list_t; + + // ///////////////////////////////// + // Private data members + + bool throwExceptions_; + bool recogniseAllOptions_; + bool addOutputSetupOptions_; + std::string doc_string_; + mutable options_list_t options_list_; + options_documentation_list_t options_documentation_list_; + enum_opt_data_list_t enum_opt_data_list_; + + bool output_all_front_matter_; + bool output_show_line_prefix_; + bool output_show_tab_count_; + bool output_show_proc_rank_; + int output_to_root_rank_only_; + + bool added_extra_output_setup_options_; + bool in_add_extra_output_setup_options_; + + static const bool output_all_front_matter_default_; + static const bool output_show_line_prefix_default_; + static const bool output_show_tab_count_default_; + static const bool output_show_proc_rank_default_; + static const int output_to_root_rank_only_default_; + + // ///////////////////////////////// + // Private member functions + + // Set the extra output setup options + void add_extra_output_setup_options() const; + + // Set an integer enumeration option + void setEnumOption( + const char enum_option_name[] + ,int *enum_option_val + ,const int num_enum_opt_values + ,const int enum_opt_values[] + ,const char* enum_opt_names[] + ,const char documentation[] + ,const bool required + ); + + // Set an enum int option + bool set_enum_value( + int argv_i + ,char* argv[] + ,const std::string &enum_opt_name + ,const int enum_id + ,const std::string &enum_str_val + ,std::ostream *errout + ) const; + + // Print the valid enum values + void print_enum_opt_names( + const int enum_id + ,std::ostream &out + ) const; + + // Return the name of the default value for an enum + std::string enum_opt_default_val_name( + const std::string &enum_name + ,const int enum_id + ,std::ostream *errout + ) const; + + // Return the index given and option value + int find_enum_opt_index( + const std::string &enum_opt_name + ,const int opt_value + ,const enum_opt_data_t &enum_data + ,std::ostream *errout + ) const; + + // Get the option and the value from an entry in argv[]. + // Will return false if entry is not formated properly. + bool get_opt_val( + const char str[] + ,std::string *opt_name + ,std::string *opt_val_str // May be empty on return + ) const; + + // String for option type + std::string opt_type_str( EOptType ) const; + + // Print bad option + void print_bad_opt( + int argv_i + ,char* argv[] + ,std::ostream *errout + ) const; + +}; // end class CommandLineProcessor + +// ///////////////////////// +// Inline members + +// Behavior modes + +inline +void CommandLineProcessor::throwExceptions( const bool & throwExceptions ) +{ throwExceptions_ = throwExceptions; } + +inline +bool CommandLineProcessor::throwExceptions() const +{ return throwExceptions_; } + +inline +void CommandLineProcessor::recogniseAllOptions( const bool & recogniseAllOptions ) +{ recogniseAllOptions_ = recogniseAllOptions; } + +inline +bool CommandLineProcessor::recogniseAllOptions() const +{ return recogniseAllOptions_; } + +inline +void CommandLineProcessor::addOutputSetupOptions( const bool &addOutputSetupOptions ) +{ addOutputSetupOptions_ = addOutputSetupOptions; } + +inline +bool CommandLineProcessor::addOutputSetupOptions() const +{ return addOutputSetupOptions_; } + +template +inline +void CommandLineProcessor::setOption( + const char enum_option_name[] + ,EType *enum_option_val + ,const int num_enum_opt_values + ,const EType enum_opt_values[] + ,const char* enum_opt_names[] + ,const char documentation[] + ,const bool required + ) +{ + // RAB: 2004/05/25: Every C++ implementation that I know of just + // represents enumerations as int's and therefore this will compile + // just fine. However, the ISO/ANSI C++ standard says that + // compilers are allowed to use a smaller storage type for an enum + // but must not require storage any larger than an 'int'. If the + // below compile-time assertion does not compile then we need to do + // something different but it will be a lot of work! + CompileTimeAssert(); + //CompileTimeAssert(); // Uncomment to see compilation error + setEnumOption( + enum_option_name + ,reinterpret_cast(enum_option_val) + ,num_enum_opt_values + ,reinterpret_cast(enum_opt_values) + ,enum_opt_names + ,documentation + ,required + ); +} + +inline +std::string CommandLineProcessor::opt_type_str( EOptType opt_type ) const +{ + std::string str; + switch( opt_type ) { + case OPT_BOOL_TRUE: + str = "bool"; + break; + case OPT_INT: + str = "int"; + break; + case OPT_DOUBLE: + str = "double"; + break; + case OPT_STRING: + str = "string"; + break; + case OPT_ENUM_INT: + str = "enum"; + break; + default: + assert(0); // Local programming error only + } + return str; +} + +} // end namespace Teuchos + +#endif // TEUCHOS_COMMAND_LINE_PROCESSOR_HPP diff --git a/fastlib/trilinos/include/Teuchos_CompObject.hpp b/fastlib/trilinos/include/Teuchos_CompObject.hpp new file mode 100644 index 0000000000..f5ebf8caed --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_CompObject.hpp @@ -0,0 +1,119 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef TEUCHOS_COMPOBJECT_HPP +#define TEUCHOS_COMPOBJECT_HPP + +/*! \file Teuchos_CompObject.hpp + \brief Object for storing data and providing functionality that is common to all + computational classes. +*/ + +#include "Teuchos_Object.hpp" +#include "Teuchos_Flops.hpp" + +/*! \class Teuchos::CompObject + \brief Functionality and data that is common to all computational classes. + + The Teuchos::CompObject is a base class for all Teuchos computational objects. It provides the basic + mechanisms and interface specifications for floating point operations using Teuchos::Flops objects. +*/ + +namespace Teuchos +{ +class CompObject +{ + + public: + + //! @name Constructors/Destructor. + //@{ + + //! Default constructor + CompObject(); + + //! Copy Constructor + CompObject(const CompObject &source); + + //! Destructor + virtual ~CompObject(); + //@} + + //! @name Set/Get counter method. + //@{ + //! Set the internal Teuchos::Flops() pointer. + void setFlopCounter(const Flops &FlopCounter) {flopCounter_= (Flops *) &FlopCounter; return;} + + //! Set the internal Teuchos::Flops() pointer to the flop counter of another Teuchos::CompObject. + void setFlopCounter(const CompObject &compObject) {flopCounter_= (Flops *) (compObject.getFlopCounter()); return;} + + //! Set the internal Teuchos::Flops() pointer to 0 (no flops counted). + void unsetFlopCounter() {flopCounter_=0; return;} + + //! Get the pointer to the Teuchos::Flops() object associated with this object, returns 0 if none. + Flops * getFlopCounter() const {return(flopCounter_);} + //@} + + //! @name Set flop count methods. + //@{ + //! Resets the number of floating point operations to zero for \e this multi-std::vector. + void resetFlops() const {if (flopCounter_!=0) flopCounter_->resetFlops(); return;} + + //! Returns the number of floating point operations with \e this multi-std::vector. + double getFlops() const {if (flopCounter_!=0) return(flopCounter_->flops()); else return(0.0);} + //@} + + //! @name Update flop count methods. + //@{ + //! Increment Flop count for \e this object + void updateFlops(int addflops) const { if (flopCounter_!=0) flopCounter_->updateFlops(addflops); return;} + + //! Increment Flop count for \e this object + void updateFlops(long int addflops) const { if (flopCounter_!=0) flopCounter_->updateFlops(addflops); return;} + + //! Increment Flop count for \e this object + void updateFlops(double addflops) const { if (flopCounter_!=0) flopCounter_->updateFlops(addflops); return;} + + //! Increment Flop count for \e this object + void updateFlops(float addflops) const {if (flopCounter_!=0) flopCounter_->updateFlops(addflops); return;} + //@} + + protected: + + Flops *flopCounter_; + +}; + + // #include "Teuchos_CompObject.cpp" + +} // namespace Teuchos + +#endif // end of TEUCHOS_COMPOBJECT_HPP diff --git a/fastlib/trilinos/include/Teuchos_CompileTimeAssert.hpp b/fastlib/trilinos/include/Teuchos_CompileTimeAssert.hpp new file mode 100644 index 0000000000..55a7fa0e23 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_CompileTimeAssert.hpp @@ -0,0 +1,59 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_COMPILE_TIME_ASSERT_HPP +#define TEUCHOS_COMPILE_TIME_ASSERT_HPP + +/*! \file Teuchos_CompileTimeAssert.hpp + \brief Template classes for testing assertions at compile time. +*/ + +#include "Teuchos_ConfigDefs.hpp" + +namespace Teuchos { + +/*! \defgroup CompileTimeAssert_grp Template classes for testing assertions at compile time. + \ingroup teuchos_language_support_grp +*/ +///@{ + +/// If instantiated (for Test!=0) then this should not compile! +template +class CompileTimeAssert { + int compile_time_assert_failed[Test-1000]; // Should not compile if instantiated! +}; + +/// If instantiated (i.e. Test==0) then this will compile! +template <> +class CompileTimeAssert<0> {}; + +///@} + +} // namespace Teuchos + +#endif // TEUCHOS_COMPILE_TIME_ASSERT_HPP diff --git a/fastlib/trilinos/include/Teuchos_ConfigDefs.hpp b/fastlib/trilinos/include/Teuchos_ConfigDefs.hpp new file mode 100644 index 0000000000..680d027ca6 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ConfigDefs.hpp @@ -0,0 +1,157 @@ +/* +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER +*/ + +#ifndef TEUCHOS_CONFIGDEFS_HPP +#define TEUCHOS_CONFIGDEFS_HPP + +/*! \file Teuchos_ConfigDefs.hpp + \brief Teuchos header file which uses auto-configuration information + to include necessary C++ headers. +*/ + +/* + * The macros PACKAGE, PACKAGE_NAME, etc, get defined for each package and need to + * be undef'd here to avoid warnings when this file is included from another package. + * KL 11/25/02 + */ + +#ifdef PACKAGE +#undef PACKAGE +#endif + +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif + +#ifdef PACKAGE_BUGREPORT +#undef PACKAGE_BUGREPORT +#endif + +#ifdef PACKAGE_STRING +#undef PACKAGE_STRING +#endif + +#ifdef PACKAGE_TARNAME +#undef PACKAGE_TARNAME +#endif + +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif + +#ifdef VERSION +#undef VERSION +#endif + +#ifdef HAVE_NUMERIC_LIMITS +#undef HAVE_NUMERIC_LIMITS +#endif + +#include "Teuchos_config.h" + +#ifdef HAVE_TEUCHOS_DEBUG +# define TEUCHOS_DEBUG +# define HAVE_TEUCHOS_ARRAY_BOUNDSCHECK +#endif + +#ifdef __cplusplus + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Teuchos { class DummyDummyClass; } +// Above, is used for a dumb reason (see +// Teuchs_StandardMemberCompositionMacros.hpp). + +const double Teuchos_MinDouble = 1.0E-100; +const double Teuchos_MaxDouble = 1.0E+100; +const double Teuchos_Overflow = 1.79E308; // Used to test if equilibration should be done. +const double Teuchos_Underflow = 2.23E-308; + +// 2007/06/29: These are hacks for std::ostringstream that should be removed +// now what we assume that a faily complete standard C++ library is available. + +#define TEUCHOS_OSTRINGSTREAM_GET_C_STR(OSS) (OSS).str().c_str() +typedef std::ostringstream TeuchosOStringStream; + +#endif /* __cplusplus */ + +/* Delete any previous definition of TEUCHOS_NO_ERROR_REPORTS */ + +#ifdef TEUCHOS_CHK_ERR +#undef TEUCHOS_CHK_ERR +#endif +#ifdef TEUCHOS_CHK_PTR +#undef TEUCHOS_CHK_PTR +#endif +#ifdef TEUCHOS_CHK_REF +#undef TEUCHOS_CHK_REF +#endif + +/* The integral type that is used for the largest std::vector space */ +typedef int Teuchos_Index; /* ToDo: Determine this in configure for the machine */ + +/* Make error report silent by defining TEUCHOS_NO_ERROR_REPORTS */ + +#define TEUCHOS_CHK_ERR(a) { if (a != 0) return(a);} +#define TEUCHOS_CHK_PTR(a) { return(a);} +#define TEUCHOS_CHK_REF(a) { return(a);} + +#ifdef __cplusplus +const int Teuchos_DefaultTracebackMode = 1; /* Default value for traceback behavior */ +#endif /* __cplusplus */ + +/* Define some macros */ +#define TEUCHOS_MAX(x,y) (( (x) > (y) ) ? (x) : (y) ) /* max function */ +#define TEUCHOS_MIN(x,y) (( (x) < (y) ) ? (x) : (y) ) /* min function */ +#define TEUCHOS_SGN(x) (( (x) < 0.0 ) ? -1.0 : 1.0 ) /* sign function */ + +#endif /* TEUCHOS_CONFIGDEFS_HPP */ diff --git a/fastlib/trilinos/include/Teuchos_ConstNonconstObjectContainer.hpp b/fastlib/trilinos/include/Teuchos_ConstNonconstObjectContainer.hpp new file mode 100644 index 0000000000..42726e4f2f --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ConstNonconstObjectContainer.hpp @@ -0,0 +1,114 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_CONST_NONCONST_OBJECT_CONTAINER_HPP +#define TEUCHOS_CONST_NONCONST_OBJECT_CONTAINER_HPP + +#include "Teuchos_RCP.hpp" + +namespace Teuchos { + +/** \brief Simple class for containing an object and protecting const with + * a runtime check which throws an std::exception. + * + * This class is simple enough and developers are encouraged to look at the + * simple inline definition of this class. + * + * The default copy constructor and assignment operator functions are allowed + * and result in shallow copied (i.e. just the RCP objects are copied). + * However, the protection of const will be maintained in the copied/assigned + * objects as well. + */ +template +class ConstNonconstObjectContainer { +public: + /** \brief. Constructs to uninitialized */ + ConstNonconstObjectContainer() + :constObj_(null),isConst_(true) {} + /** \brief. Calls initialize() with a non-const object. */ + ConstNonconstObjectContainer( const RCP &obj ) + { initialize(obj); } + /** \brief. Calls initialize() with a const object. */ + ConstNonconstObjectContainer( const RCP &obj ) + { initialize(obj); } + /** \brief. Initialize using a non-const object. + * Allows both const and non-const access to the contained object. */ + void initialize( const RCP &obj ) + { TEST_FOR_EXCEPT(!obj.get()); constObj_=obj; isConst_=false; } + /** \brief. Initialize using a const object. + * Allows only const access enforced with a runtime check. */ + void initialize( const RCP &obj ) + { TEST_FOR_EXCEPT(!obj.get()); constObj_=obj; isConst_=true; } + /** \brief. Uninitialize. */ + void uninitialize() + { constObj_=null; isConst_=true; } + /** \brief Returns true if const-only access to the object is allowed. */ + bool isConst() const + { return isConst_; } + /** \brief Get an RCP to the non-const contained object. + * + * Preconditions: + *
      + *
    • [getConstObj().get()!=NULL] isConst()==false + *
    + * + * Postconditions: + *
      + *
    • [getConstObj().get()==NULL] return.get()==NULL + *
    • [getConstObj().get()!=NULL] return.get()!=NULL + *
    + */ + RCP getNonconstObj() + { + TEST_FOR_EXCEPTION( + constObj_.get() && isConst_, std::logic_error + ,"Error, the object of reference type \""<::name()<<"\" was given " + "as a const-only object and non-const access is not allowed." + ); + return rcp_const_cast(constObj_); + } + /** \brief Get an RCP to the const contained object. + * + * If return.get()==NULL, then this means that no object was given + * to *this data container object. + */ + RCP getConstObj() const + { return constObj_; } + /** \brief Perform shorthand for getConstObj(). */ + RCP operator()() const + { return getConstObj(); } + +private: + RCP constObj_; + bool isConst_; +}; + +} // namespace Teuchos + + +#endif // TEUCHOS_CONST_NONCONST_OBJECT_CONTAINER_HPP diff --git a/fastlib/trilinos/include/Teuchos_DataAccess.hpp b/fastlib/trilinos/include/Teuchos_DataAccess.hpp new file mode 100644 index 0000000000..7b948c5baf --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_DataAccess.hpp @@ -0,0 +1,54 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef _TEUCHOS_DATAACCESS_HPP_ +#define _TEUCHOS_DATAACCESS_HPP_ + +/*! \file Teuchos_DataAccess.hpp + \brief Teuchos::DataAccess Mode enumerable type +*/ + +namespace Teuchos { + + /*! \enum DataAccess + If set to Copy, user data will be copied at construction. + If set to View, user data will be encapsulated and used throughout + the life of the object. + */ + + enum DataAccess { + Copy, /*!< User data will be copied at construction. */ + View /*!< User data will be encapsulated and used throughout the life of the object. */ + }; + +} // namespace Teuchos + +#endif /* _TEUCHOS_DATAACCESS_HPP_ */ diff --git a/fastlib/trilinos/include/Teuchos_DefaultComm.hpp b/fastlib/trilinos/include/Teuchos_DefaultComm.hpp new file mode 100644 index 0000000000..f0afe062f6 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_DefaultComm.hpp @@ -0,0 +1,110 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_DEFAULT_COMM_HPP +#define TEUCHOS_DEFAULT_COMM_HPP + +#include "Teuchos_RCP.hpp" +#include "Teuchos_DefaultSerialComm.hpp" +#ifdef HAVE_MPI +# include "Teuchos_DefaultMpiComm.hpp" +#endif + +namespace Teuchos { + +/** \brief Returns a default global communicator appropriate for the + * enviroment. + * + * If HAVE_MPI is defined, then an instance of MpiComm will be + * created from MPI_COMM_WORLD. Otherwise, a SerialComm + * is returned. + */ +template +class DefaultComm { +public: + + /** \brief Return the default glocal communicator. + * + * Note that this function can not be called until after MPI has been + * initialized if MPI is expected! + */ + static Teuchos::RCP > getComm(); + + /** \brief Return a serial comm if the input comm in null. + */ + static Teuchos::RCP > + getDefaultSerialComm( const Teuchos::RCP > &comm ); + +private: + + static Teuchos::RCP > comm_; + static Teuchos::RCP > defaultSerialComm_; + +}; + +// /////////////////////////// +// Template Implementations + +template +Teuchos::RCP > +DefaultComm::getComm() +{ + if(!comm_.get()) { +#ifdef HAVE_MPI + comm_ = rcp(new MpiComm(opaqueWrapper((MPI_Comm)MPI_COMM_WORLD))); +#else // HAVE_MPI + comm_ = rcp(new SerialComm()); +#endif // HAVE_MPI + } + return comm_; +} + +template +Teuchos::RCP > +DefaultComm::getDefaultSerialComm( + const Teuchos::RCP > &comm + ) +{ + if( comm.get() ) + return comm; + else + return defaultSerialComm_; +} + +template +Teuchos::RCP > +DefaultComm::comm_ = Teuchos::null; + +template +Teuchos::RCP > +DefaultComm::defaultSerialComm_ += Teuchos::rcp(new Teuchos::SerialComm()); + +} // namespace Teuchos + +#endif // TEUCHOS_DEFAULT_COMM_HPP diff --git a/fastlib/trilinos/include/Teuchos_DefaultSerialComm.hpp b/fastlib/trilinos/include/Teuchos_DefaultSerialComm.hpp new file mode 100644 index 0000000000..0f15645699 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_DefaultSerialComm.hpp @@ -0,0 +1,226 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_SERIAL_COMM_HPP +#define TEUCHOS_SERIAL_COMM_HPP + +#include "Teuchos_Comm.hpp" +#include "Teuchos_OrdinalTraits.hpp" + +namespace Teuchos { + +/** \brief Concrete serial communicator subclass. + * + * ToDo: Finish documentation! + */ +template +class SerialComm : public Comm { +public: + + //! @name Constructors + //@{ + + /** \brief . */ + SerialComm(); + + //@} + + //! @name Overridden from Comm + //@{ + + /** \brief . */ + int getRank() const; + /** \brief . */ + int getSize() const; + /** \brief . */ + void barrier() const; + /** \brief . */ + void broadcast( + const int rootRank, const Ordinal bytes, char buffer[] + ) const; + /** \brief . */ + void gatherAll( + const Ordinal sendBytes, const char sendBuffer[] + ,const Ordinal recvBytes, char recvBuffer[] + ) const; + /** \brief . */ + void reduceAll( + const ValueTypeReductionOp &reductOp + ,const Ordinal bytes, const char sendBuffer[], char globalReducts[] + ) const; + /** \brief . */ + void reduceAllAndScatter( + const ValueTypeReductionOp &reductOp + ,const Ordinal sendBytes, const char sendBuffer[] + ,const Ordinal recvCounts[], const Ordinal blockSize, char myGlobalReducts[] + ) const; + /** \brief . */ + void scan( + const ValueTypeReductionOp &reductOp + ,const Ordinal bytes, const char sendBuffer[], char scanReducts[] + ) const; + /** \brief . */ + void send( + const Ordinal bytes, const char sendBuffer[], const int destRank + ) const; + /** \brief . */ + int receive( + const int sourceRank, const Ordinal bytes, char recvBuffer[] + ) const; + + //@} + + //! @name Overridden from Describable + //@{ + + /** \brief . */ + std::string description() const; + + //@} + +}; + +// //////////////////////// +// Implementations + +// Constructors + +template +SerialComm::SerialComm() +{} + +// Overridden from Comm + +template +int SerialComm::getRank() const +{ + return 0; +} + +template +int SerialComm::getSize() const +{ + return 1; +} + +template +void SerialComm::barrier() const +{ + // Nothing to do +} + +template +void SerialComm::broadcast( + const int rootRank, const Ordinal bytes, char buffer[] + ) const +{ + // Nothing to do +} + +template +void SerialComm::gatherAll( + const Ordinal sendBytes, const char sendBuffer[] + ,const Ordinal recvBytes, char recvBuffer[] + ) const +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT(!(sendBytes==recvBytes)); +#endif + std::copy(sendBuffer,sendBuffer+sendBytes,recvBuffer); +} + +template +void SerialComm::reduceAll( + const ValueTypeReductionOp &reductOp + ,const Ordinal bytes, const char sendBuffer[], char globalReducts[] + ) const +{ + std::copy(sendBuffer,sendBuffer+bytes,globalReducts); +} + +template +void SerialComm::reduceAllAndScatter( + const ValueTypeReductionOp &reductOp + ,const Ordinal sendBytes, const char sendBuffer[] + ,const Ordinal recvCounts[], const Ordinal blockSize, char myGlobalReducts[] + ) const +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT( recvCounts==NULL || blockSize*recvCounts[0] != sendBytes ); +#endif + std::copy(sendBuffer,sendBuffer+sendBytes,myGlobalReducts); +} + +template +void SerialComm::scan( + const ValueTypeReductionOp &reductOp + ,const Ordinal bytes, const char sendBuffer[], char scanReducts[] + ) const +{ + std::copy(sendBuffer,sendBuffer+bytes,scanReducts); +} + +template +void SerialComm::send( + const Ordinal bytes, const char sendBuffer[], const int destRank + ) const +{ + TEST_FOR_EXCEPTION( + true, std::logic_error + ,"SerialComm::send(...): Error, you can not call send(...) when you" + " only have one process!" + ); +} + +template +int SerialComm::receive( + const int sourceRank, const Ordinal bytes, char recvBuffer[] + ) const +{ + TEST_FOR_EXCEPTION( + true, std::logic_error + ,"SerialComm::receive(...): Error, you can not call receive(...) when you" + " only have one process!" + ); + // The next line will never be reached, but a return is required on some platforms + return 0; +} + +// Overridden from Describable + +template +std::string SerialComm::description() const +{ + std::ostringstream oss; + oss << "Teuchos::SerialComm<"<::name()<<">"; + return oss.str(); +} + +} // namespace Teuchos + +#endif // TEUCHOS_SERIAL_COMM_HPP diff --git a/fastlib/trilinos/include/Teuchos_Describable.hpp b/fastlib/trilinos/include/Teuchos_Describable.hpp new file mode 100644 index 0000000000..906accdee2 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Describable.hpp @@ -0,0 +1,242 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_DESCRIBABLE_HPP +#define TEUCHOS_DESCRIBABLE_HPP + +#include "Teuchos_VerbosityLevel.hpp" +#include "Teuchos_FancyOStream.hpp" +#include "Teuchos_LabeledObject.hpp" + + +namespace Teuchos { + + +/** \brief Base class for all objects that can describe themselves and + * their current state. + * + * This base class is designed to be a minimally invasive approach for + * allowing subclasses to optionally provide detailed debug-style information + * about their current state. This interface has just two virtual member + * functions, describe(void) and description(), which both + * have default implementations. The shorter version description() + * (which takes no arguments and returns an std::string object) is + * meant for very short one-line descriptions while the longer version + * describe() takes and returns a FancyOStream object and is + * designed for more detailed multi-line formated output. + * + * Since both of these functions have reasonable default implementations, when + * a subclass inherits from this base class, no virtual functions need to be + * overridden to start with. However, when debugging time comes, one or both + * of these functions should be overridden to provide more useful information. + * + * This interface derives from the LabeledObject interface and + * therefore a user can set an object-specific label on every + * Describable object that will be incorporated in the the + * description of the object. + * + * ToDo: Include an example/testing function for a few different use + * cases to demonstrate how to use this interface properly. + * + * \ingroup teuchos_outputting_grp + */ +class Describable : virtual public LabeledObject { +public: + + /// Default value for verLevel in description() + static const EVerbosityLevel verbLevel_default; + + //! @name Public virtual member functions + //@{ + + /** \brief Return a simple one-line description of this object. + * + * The default implementation just returns typeName(*this), along + * with the object's label if defined. The function + * typeName(*this) guarantees that a demangled, human-readable + * name is returned on most platforms. Even if subclasses choose to + * override this function, this default implementation can still be called + * as Teuchos::Describable::description() in order to print the + * label name along with the class name. + */ + virtual std::string description() const; + + /** \brief Print the object with some verbosity level to an + * FancyOStream object. + * + * \param out + * [in] The FancyOStream object that output is sent to. + * \param verbLevel + * [in] Determines the level of verbosity for which the the object + * will be printed. If verbLevel==VERB_DEFAULT (which is + * the default value), then the verbosity level will be determined + * by the *this object (i.e. perhaps through the + * ObjectWithVerbosity interface). It is up to + * *this how to interpret the level represented by + * verbLevel. The default value is + * VERB_DEFAULT. + * + * In order for this function to work effectively for independently + * developed classes, a general consensus needs be reached as to + * what the various verbosity levels represented in + * verbLevel mean in relation to the amount of output + * produced. + * + * It is expected that the subclass implementation will tab the output one + * increment using the OSTab class. This convention results in + * orderly output from independently written subclasses. + * + * A default implementation of this function is provided that simply + * performs: + \code + + OSTab tab(out); + return out << this->description() << std::endl; \endcode + * + * A subclass should override this function to provide more + * interesting and more useful information about the object. + */ + virtual void describe( + FancyOStream &out, + const EVerbosityLevel verbLevel = verbLevel_default + ) const; + +}; + + +// Describable stream manipulator state class +// +// This is not a class that a user needs to see and that is why it is not +// being given doxygen documentation! +struct DescribableStreamManipulatorState { + const Describable &describable; + const EVerbosityLevel verbLevel; + DescribableStreamManipulatorState( + const Describable &_describable, + const EVerbosityLevel _verbLevel = VERB_MEDIUM + ) + :describable(_describable) + ,verbLevel(_verbLevel) + {} +}; + + +/** \brief Describable output stream manipulator. + * + * This simple function allows you to insert output from + * Describable::describe() right in the middle of a chain of + * insertion operations. For example, you can write: + + \code + + void someFunc( const Teuchos::Describable &obj ) + { + ... + std::cout + << "The object is described as " + << describe(obj,Teuchos::VERB_MEDIUM); + ... + } + + \endcode + + * \relates Describable + */ +inline DescribableStreamManipulatorState describe( + const Describable &describable, + const EVerbosityLevel verbLevel = Describable::verbLevel_default + ) +{ + return DescribableStreamManipulatorState(describable,verbLevel); +} + + +/** \brief Output stream operator for Describable manipulator. + * + * To call this function use something like: + + \code + + void someFunc( const Teuchos::Describable &obj ) + { + ... + std::cout + << "The object is described as " + << describe(obj,Teuchos::VERB_MEDIUM); + ... + } + + \endcode + + * Note: The input std::ostream is casted to a FancyOStream + * object before calling Describable::describe() on the underlying + * Describable object. There is no way around this since this + * function must be written in terms of std::ostream rather than + * FancyOStream if one is to write compound output statements + * involving primitive data types. + * + * \relates Describable + */ +inline +std::ostream& operator<<( + std::ostream& os, const DescribableStreamManipulatorState& d + ) +{ + d.describable.describe(*getFancyOStream(Teuchos::rcp(&os,false)),d.verbLevel); + return os; +} + +// +// RAB: Note: The above function works with an std::ostream object even +// through Describable::describe(...) requires a FancyOStream object. We must +// write the stream manipulator in terms of std::ostream, or compound output +// statements like: +// +// void foo( FancyOStream &out, Describable &d, EVerbLevel verbLevel ) +// { +// out << "\nThis is the describable object d:" << describe(d,verbLevel); +// } +// +// will not work correctly. The problem is that the first output +// +// out << "\nThis is the describable object d:" +// +// must return a reference to an std::ostream object. This should mean that +// the next statement, which is basically: +// +// static_cast(out) << DescribableStreamManipulatorState +// +// should not even compile. However, under gcc 3.4.3, the code did compile +// but did not call the above function. Instead, it set up some type of +// infinite recursion that resulted in a segfault due to the presence of the +// Teuchos::any class! +// + + +} // namespace Teuchos + +#endif // TEUCHOS_DESCRIBABLE_HPP diff --git a/fastlib/trilinos/include/Teuchos_ErrorPolling.hpp b/fastlib/trilinos/include/Teuchos_ErrorPolling.hpp new file mode 100644 index 0000000000..4bbe9c04de --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ErrorPolling.hpp @@ -0,0 +1,115 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_ERRORPOLLING_H +#define TEUCHOS_ERRORPOLLING_H + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_TestForException.hpp" + +/*! \defgroup ErrorPolling_grp Utility code for synchronizing std::exception detection across processors. +*/ +//@{ + +namespace Teuchos +{ + class MPIComm; + + /** \brief ErrorPolling provides utilities for establishing agreement + * between processors on whether an std::exception has been detected on any one + * processor. + * + * The two functions must be used in a coordinated way. The simplest use + * case is to embed a call to reportFailure() whenever an std::exception is + * detected at the top-level try/catch block, and then to do a call to + * pollForFailures() whenever it is desired to check for off-processor + * errors before proceeding. The macro + + \code + TEUCHOS_TEST_FOR_FAILURE(comm); + \endcode + + * calls pollForFailures() and throws an std::exception if the return value is + * true. + * + * Polling is a collective operation (an MPI_Reduce) and so incurs some + * performance overhead. It can be disabled with a call to + * \code + * Teuchos::ErrorPolling::disable(); + * \endcode + * IMPORTANT: all processors must agree on whether collective error checking + * is enabled or disabled. If there are inconsistent states, the reduction + * operations in pollForFailures() will hang because some processors cannot be + * contacted. + */ + class ErrorPolling + { + public: + /** Call this function upon catching an std::exception in order to + * inform other processors of the error. This function will do an + * AllReduce in conjunction with calls to either this function or + * its partner, pollForFailures(), on the other processors. This + * procedure has the effect of communicating to the other + * processors that an std::exception has been detected on this one. */ + static void reportFailure(const MPIComm& comm); + + /** Call this function after std::exception-free completion of a + * try/catch block. This function will do an AllReduce in + * conjunction with calls to either this function or its partner, + * reportFailure(), on the other processors. If a failure has been + * reported by another processor, the call to pollForFailures() + * will return true and an std::exception can be thrown. */ + static bool pollForFailures(const MPIComm& comm); + + /** Activate error polling */ + static void enable() {isActive()=true;} + + /** Disable error polling */ + static void disable() {isActive()=false;} + + private: + /** Set or check whether error polling is active */ + static bool& isActive() {static bool rtn = true; return rtn;} + }; + + /** + * This macro polls all processors in the given communicator to find + * out whether an error has been reported by a call to + * ErrorPolling::reportFailure(comm). + * + * @param comm [in] The communicator on which polling will be done + */ +#define TEUCHOS_POLL_FOR_FAILURES(comm) \ + TEST_FOR_EXCEPTION(Teuchos::ErrorPolling::pollForFailures(comm), \ + std::runtime_error, \ + "off-processor error detected by proc=" << (comm).getRank()); +} + +//@} + +#endif diff --git a/fastlib/trilinos/include/Teuchos_ExpatHandlerAdapter.hpp b/fastlib/trilinos/include/Teuchos_ExpatHandlerAdapter.hpp new file mode 100644 index 0000000000..e8b79f2624 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ExpatHandlerAdapter.hpp @@ -0,0 +1,64 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_EXPATHANDLERADAPTER_H +#define TEUCHOS_EXPATHANDLERADAPTER_H + +/*! \file Teuchos_ExpatHandlerAdapter.hpp + \brief Expat adapter for the TreeBuildingXMLHandler +*/ + +#include "Teuchos_ConfigDefs.hpp" + +#ifdef HAVE_TEUCHOS_EXPAT + +#include "Teuchos_TreeBuildingXMLHandler.hpp" +#include "Teuchos_RCP.hpp" + +#include "expat.h" + +extern "C" +{ + /** \ingroup XML Expat callback for start of an XML element. */ + void expatStartElementHandler(void* handler, + const XML_Char* name, + const XML_Char** attr); + + /** \ingroup XML Expat callback for end of an XML element. */ + void expatEndElementHandler(void* handler, + const XML_Char* name); + + /** \ingroup XML Expat callback for character data. */ + void expatCharacterDataHandler(void* handler, + const XML_Char* s, + int len); +} + +#endif // HAVE_TEUCHOS_EXPAT + +#endif // TEUCHOS_EXPATHANDLERADAPTER_H diff --git a/fastlib/trilinos/include/Teuchos_F77_wrappers.h b/fastlib/trilinos/include/Teuchos_F77_wrappers.h new file mode 100644 index 0000000000..1f5a16893b --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_F77_wrappers.h @@ -0,0 +1,117 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef _TEUCHOS_F77_WRAPPERS_H_ +#define _TEUCHOS_F77_WRAPPERS_H_ + +/*! \file Teuchos_F77_wrappers.h + \brief Macros for portably calling Fortran77 from C/C++ +*/ + +#include "Teuchos_ConfigDefs.hpp" + +/* Define fcd (Fortran Teuchos_fcd descriptor) for non-standard situations */ + +#if defined(CRAY_T3X) + +# include +# define F77_CALL_PREFIX +# define FORTRAN_CHAR_1_ARG(ARG_NAME) fcd* ARG_NAME +# define FORTRAN_CONST_CHAR_1_ARG(ARG_NAME) const fcd& ARG_NAME +# define FORTRAN_CHAR_1_ARG_CALL(ARG_NAME) ARG_NAME + +#elif defined(INTEL_CXML) + +# define F77_CALL_PREFIX __stdcall +# define FORTRAN_CHAR_1_ARG(ARG_NAME) char* ARG_NAME, unsigned int +# define FORTRAN_CONST_CHAR_1_ARG(ARG_NAME) const char& ARG_NAME, unsigned int +# define FORTRAN_CHAR_1_ARG_CALL(ARG_NAME) ARG_NAME, 1 + +#elif defined(INTEL_MKL) + +# define F77_CALL_PREFIX +# define FORTRAN_CHAR_1_ARG(ARG_NAME) char* ARG_NAME +# define FORTRAN_CONST_CHAR_1_ARG(ARG_NAME) const char& ARG_NAME +# define FORTRAN_CHAR_1_ARG_CALL(ARG_NAME) ARG_NAME, 1 + +#else + +# define F77_CALL_PREFIX +# define FORTRAN_CHAR_1_ARG(ARG_NAME) char* ARG_NAME +# define FORTRAN_CONST_CHAR_1_ARG(ARG_NAME) const char& ARG_NAME +# define FORTRAN_CHAR_1_ARG_CALL(ARG_NAME) ARG_NAME + +#endif + +/* RAB: 20030924: ToDo: Find a way to see if const is supported or not by C or + just decide that this will only be for C++ code and be done with it. */ + +/* External macros */ + +#define FORTRAN_NAME_UL(UNAME,LNAME) F77_FUNC(LNAME,UNAME) + +#define FORTRAN_FUNC_DECL_UL(TYPE,UFUNC_NAME,LFUNC_NAME) TYPE F77_CALL_PREFIX FORTRAN_NAME_UL(UFUNC_NAME,LFUNC_NAME) + +#define FORTRAN_FUNC_CALL_UL(UFUNC_NAME,LFUNC_NAME) FORTRAN_NAME_UL(UFUNC_NAME,LFUNC_NAME) + +#define FORTRAN_FUNC_PTR_DECL_UL(TYPE,UFUNC_NAME,LFUNC_NAME) TYPE (F77_CALL_PREFIX *FORTRAN_NAME_UL(UFUNC_NAME,LFUNC_NAME)) + +#define FORTRAN_COMMMON_BLOCK_NAME_UL(UNAME,LNAME) FORTRAN_NAME_UL(UNAME,LNAME)\ + +#define FORTRAN_NAME_UL_(UNAME,LNAME) F77_FUNC_(LNAME,UNAME) + +#define FORTRAN_FUNC_DECL_UL_(TYPE,UFUNC_NAME,LFUNC_NAME) TYPE F77_CALL_PREFIX FORTRAN_NAME_UL_(UFUNC_NAME,LFUNC_NAME) + +#define FORTRAN_FUNC_CALL_UL_(UFUNC_NAME,LFUNC_NAME) FORTRAN_NAME_UL_(UFUNC_NAME,LFUNC_NAME) + +#define FORTRAN_FUNC_PTR_DECL_UL_(TYPE,UFUNC_NAME,LFUNC_NAME) TYPE (F77_CALL_PREFIX *FORTRAN_NAME_UL_(UFUNC_NAME,LFUNC_NAME)) + +#define FORTRAN_COMMMON_BLOCK_NAME_UL_(UNAME,LNAME) FORTRAN_NAME_UL_(UNAME,LNAME)\ + +#ifdef __cplusplus + +// These are the platform dependent C++ equivalents of fortran types +// RAB: 2003/11/20: ToDo: Move this into Teuchos namespace at some point +namespace FortranTypes { + +typedef int f_int; // INTEGER +typedef float f_real; // REAL +typedef double f_dbl_prec; // DOUBLE PRECISION +typedef int f_logical; // LOGICAL +typedef char f_char; // CHARACTER*1 +typedef unsigned int f_char_len; // length argument for a CHARACTER*(*) +//typedef std::complex f_complex; // COMPLEX +//typedef std::complex f_complex_16; // COMPLEX*16 + +enum { F_TRUE = true, F_FALSE = false }; // Let compiler figure this out! + +#endif /* __cplusplus */ + +} // namespace FortranTypes + +#endif // _TEUCHOS_F77_WRAPPERS_H_ diff --git a/fastlib/trilinos/include/Teuchos_FILEstream.hpp b/fastlib/trilinos/include/Teuchos_FILEstream.hpp new file mode 100644 index 0000000000..3cbf093825 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_FILEstream.hpp @@ -0,0 +1,76 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2006) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_FILESTREAM_H +#define TEUCHOS_FILESTREAM_H + +//! \file Teuchos_FILEstream.hpp + +#include + +namespace Teuchos +{ + + //! Teuchos::FILEstream: Combined C FILE and C++ stream + + /*! Teuchos::FILEstream is a class that defines an object that is + simultaneously a C FILE object and a C++ stream object. The + utility of this class is in connecting existing C++ code that + uses streams and C code that uses FILEs. An important example + of this situation is the python wrappers for Trilinos packages. + Trilinos is of course written primarily in C++, but the python + wrappers must interface to the python C API. Wrappers for + Trilinos methods or operators that expect a stream can be given + a Teuchos::FILEstream, which then behaves as a FILE within the + python C API. This is a low-level object that should not be + needed at the user level. + */ + + class FILEstream : public std::streambuf { + + public: + + //! Constructor + + /*! The only constructor for Teuchos:FILEstream, and it requires a + pointer to a C FILE struct. + */ + FILEstream(std::FILE* file): self_file(file) {} + + protected: + + std::streambuf::int_type overflow(std::streambuf::int_type c) { + return std::fputc(c, self_file) == EOF? + std::streambuf::traits_type::eof(): c; + } + + FILE* self_file; + }; +} + +#endif diff --git a/fastlib/trilinos/include/Teuchos_FancyOStream.hpp b/fastlib/trilinos/include/Teuchos_FancyOStream.hpp new file mode 100644 index 0000000000..f5f41d3bdc --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_FancyOStream.hpp @@ -0,0 +1,1256 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_FANCY_O_STREAM_HPP +#define TEUCHOS_FANCY_O_STREAM_HPP + +#include "Teuchos_RCP.hpp" +#include "Teuchos_GlobalMPISession.hpp" +#include "Teuchos_oblackholestream.hpp" +#include "Teuchos_as.hpp" + +namespace Teuchos { + + +/** \brief Stream buffering class that performs the magic of indenting + * data sent to an std::ostream object. + * + * \ingroup teuchos_outputting_grp + * + * Note, this is not a user-level class. Users should use + * basic_FancyOStream. + */ +template +class basic_FancyOStream_buf : public std::basic_streambuf +{ +public: + + /** \brief . */ + typedef CharT char_type; + /** \brief . */ + typedef Traits traits_type; + /** \brief . */ + typedef typename traits_type::int_type int_type; + /** \brief . */ + typedef typename traits_type::pos_type pos_type; + /** \brief . */ + typedef typename traits_type::off_type off_type; + + /** \brief . */ + basic_FancyOStream_buf( + const RCP > &oStream + ,const std::basic_string &tabIndentStr + ,const int startingTab + ,const bool showLinePrefix + ,const int maxLenLinePrefix + ,const bool showTabCount + ,const bool showProcRank + ); + + /** \brief . */ + void initialize( + const RCP > &oStream + ,const std::basic_string &tabIndentStr + ,const int startingTab + ,const bool showLinePrefix + ,const int maxLenLinePrefix + ,const bool showTabCount + ,const bool showProcRank + ); + + /** \brief . */ + RCP > getOStream(); + + /** \brief . */ + void setTabIndentStr(const std::basic_string &tabIndentStr); + + /** \brief . */ + const std::basic_string& getTabIndentStr() const; + + /** \brief .*/ + void setShowLinePrefix(const bool showLinePrefix); + + /** \brief .*/ + bool getShowLinePrefix() const; + + /** \brief .*/ + void setMaxLenLinePrefix(const int maxLenLinePrefix); + + /** \brief .*/ + int getMaxLenLinePrefix() const; + + /** \brief . */ + void setShowTabCount(const bool showTabCount); + + /** \brief . */ + bool getShowTabCount() const; + + /** \brief . */ + void setShowProcRank(const bool showProcRank); + + /** \brief . */ + bool getShowProcRank() const; + + /** \brief .*/ + void setProcRankAndSize( const int procRank, const int numProcs ); + + /** \brief .*/ + int getProcRank() const; + + /** \brief .*/ + int getNumProcs() const; + + /** \brief . */ + void setOutputToRootOnly( const int rootRank ); + + /** \brief . */ + int getOutputToRootOnly() const; + + /** \brief . */ + void pushTab(const int tabs); + + /** \brief . */ + int getNumCurrTabs() const; + + /** \brief . */ + void popTab(); + + /** \brief . */ + void pushLinePrefix( + const std::basic_string &linePrefix + ); + + /** \brief . */ + void popLinePrefix(); + + /** \brief . */ + const std::basic_string& getTopLinePrefix() const; + + /** \brief . */ + void pushDisableTabbing(); + + /** \brief . */ + void popDisableTabbing(); + +protected: + + //! @name Protected overridden functions from std::basic_streambuf + //@{ + + /** \brief . */ + std::streamsize xsputn(const char_type* s, std::streamsize n); + + /** \brief . */ + int_type overflow(int_type c); + +#ifdef TEUCHOS_FANCY_OSTREAM_SHOW_ALL_CALLS + + void imbue(const locale& l) + { + std::cerr << "\ncalled imbue()\n"; + std::basic_streambuf::imbue(l); + } + + basic_streambuf* + setbuf(char_type* s, streamsize n) + { + std::cerr << "\ncalled setbuf()\n"; + return std::basic_streambuf::setbuf(s,n); + } + + pos_type + seekoff(off_type a, ios_base::seekdir b,ios_base::openmode c) + { + std::cerr << "\ncalled seekoff()\n"; + return std::basic_streambuf::seekoff(a,b,c); + } + + pos_type + seekpos(pos_type a, ios_base::openmode b) + { + std::cerr << "\ncalled seekpos()\n"; + return std::basic_streambuf::seekpos(a,b); + } + + int + sync() + { + std::cerr << "\ncalled sync()\n"; + return std::basic_streambuf::sync(); + } + + streamsize + showmanyc() + { + std::cerr << "\ncalled showmanyc()\n"; + return std::basic_streambuf::showmanyc(); + } + + streamsize + xsgetn(char_type* s, streamsize n) + { + std::cerr << "\ncalled xsgetn()\n"; + return std::basic_streambuf::xsgetn(s,n); + } + + int_type + underflow() + { + std::cerr << "\ncalled underflow()\n"; + return std::basic_streambuf::underflow(); + } + + int_type + uflow() + { + std::cerr << "\ncalled uflow()\n"; + return std::basic_streambuf::uflow(); + } + + int_type + pbackfail(int_type c = traits_type::eof()) + { + std::cerr << "\ncalled pbackfail()\n"; + return std::basic_streambuf::pbackfail(c); + } + +#endif // TEUCHOS_FANCY_OSTREAM_SHOW_ALL_CALLS + + //@} + +private: + + // //////////////////////// + // Private types + + typedef std::basic_string string_t; + typedef std::deque tabIndentStack_t; + typedef std::deque linePrefixStack_t; + + // //////////////////////// + // Private data members + + RCP > oStreamSet_; + RCP > oStream_; + std::basic_string tabIndentStr_; + bool showLinePrefix_; + int maxLenLinePrefix_; + bool showTabCount_; + bool showProcRank_; + int rootRank_; + int procRank_; + int numProcs_; + int rankPrintWidth_; + + RCP lineOut_; + + int tabIndent_; + tabIndentStack_t tabIndentStack_; + linePrefixStack_t linePrefixStack_; + int enableTabbingStack_; + + bool wroteNewline_; + + // //////////////////////// + // Private member functions + + std::ostream& out(); + + void writeChars( const char_type s[], std::streamsize n ); + + void writeFrontMatter(); + + // Not defined and not to be called + basic_FancyOStream_buf(); + basic_FancyOStream_buf(const basic_FancyOStream_buf&); + basic_FancyOStream_buf operator=( + const basic_FancyOStream_buf& + ); + +}; + +/** \brief std::ostream subclass that performs the magic of indenting data + * sent to an std::ostream object among other things. + * + * Use the typedef FancyOStream for support for the char + * character type. + * + * Indentation of the stream is accomplished through creating + * basic_OSTab objects. + * + * In addition to indenting output, this stream object can also print various + * types of information at the beginning of each line. The type of information + * supported is: + *
      + *
    • Processor rank: Set using setShowProcRank(). + *
    • Line prefix name: Set using showLinePrefix() and OSTab::OSTab(). + *
    • Tab counts (useful for debugging): Set using setShowTabCount(). + *
    + * + * See FancyOutputting_test.cpp for examples of how this class is + * used and the output it generates. + */ +template > +class basic_FancyOStream : public std::basic_ostream +{ +public: + + //! @name Public types + //@{ + + /** \brief . */ + typedef CharT char_type; + /** \brief . */ + typedef Traits traits_type; + /** \brief . */ + typedef typename traits_type::int_type int_type; + /** \brief . */ + typedef typename traits_type::pos_type pos_type; + /** \brief . */ + typedef typename traits_type::off_type off_type; + /** \brief . */ + + /** \brief . */ + typedef basic_FancyOStream_buf streambuf_t; + /** \brief . */ + typedef std::basic_ostream ostream_t; + + //@} + + //! @name Public client functions + //@{ + + /** \brief . */ + explicit + basic_FancyOStream( + const RCP< std::basic_ostream > &oStream + ,const std::basic_string &tabIndentStr = " " + ,const int startingTab = 0 + ,const bool showLinePrefix = false + ,const int maxLenLinePrefix = 10 + ,const bool showTabCount = false + ,const bool showProcRank = false + ); + + /** \brief . */ + void initialize( + const RCP< std::basic_ostream > &oStream + ,const std::basic_string &tabIndentStr = " " + ,const int startingTab = 0 + ,const bool showLinePrefix = false + ,const int maxLenLinePrefix = 10 + ,const bool showTabCount = false + ,const bool showProcRank = false + ); + + /** \brief. */ + RCP > getOStream(); + + /** \brief . */ + basic_FancyOStream& setTabIndentStr( + const std::basic_string &tabIndentStr + ); + + /** \brief. */ + const std::basic_string& getTabIndentStr() const; + + /** \brief Set if processor rank, line prefixes, and tab counts are shown or not .*/ + basic_FancyOStream& setShowAllFrontMatter(const bool showAllFrontMatter); + + /** \brief .*/ + basic_FancyOStream& setShowLinePrefix(const bool showLinePrefix); + + /** \brief .*/ + basic_FancyOStream& setMaxLenLinePrefix(const int maxLenLinePrefix); + + /** \brief . */ + basic_FancyOStream& setShowTabCount(const bool showTabCount); + + /** \brief . */ + basic_FancyOStream& setShowProcRank(const bool showProcRank); + + /** \brief . */ + basic_FancyOStream& setProcRankAndSize( const int procRank, const int numProcs ); + + /** \brief . */ + basic_FancyOStream& setOutputToRootOnly( const int rootRank ); + + /** \brief . */ + int getOutputToRootOnly() const; + + /** \brief . */ + void copyAllOutputOptions(const basic_FancyOStream &oStream); + + //@} + + //! @name Functions designed to be used by basic_OSTab + //@{ + + /** \brief . */ + void pushTab(const int tabs = 1); + + /** \brief . */ + int getNumCurrTabs() const; + + /** \brief . */ + void popTab(); + + /** \brief . */ + void pushLinePrefix(const std::basic_string &linePrefix); + + /** \brief . */ + void popLinePrefix(); + + /** \brief . */ + const std::basic_string& getTopLinePrefix() const; + + /** \brief . */ + void pushDisableTabbing(); + + /** \brief . */ + void popDisableTabbing(); + + //@} + +private: + + streambuf_t streambuf_; + + // Not defined and not to be called + basic_FancyOStream(); + basic_FancyOStream(const basic_FancyOStream&); + basic_FancyOStream operator=(const basic_FancyOStream&); + +}; +/** \brief Dynamically allocate a FancyOStream and return it wrapped in an RCP + * object. + * + * \relates basic_FancyOStream + */ +template +RCP > +fancyOStream( + const RCP< std::basic_ostream >& oStream, + const std::basic_string& tabIndentStr = " ", + const int startingTab = 0, + const bool showLinePrefix = false, + const int maxLenLinePrefix = 10, + const bool showTabCount = false, + const bool showProcRank = false + ) +{ + return rcp( + new basic_FancyOStream( + oStream,tabIndentStr,startingTab,showLinePrefix, + maxLenLinePrefix,showTabCount,showProcRank + ) + ); +} + +/** \brief Get a FancyOStream from an std::ostream object. + * + * If the object already is a FancyOStream, then nothing has to be done. + * Otherwise, a temp FancyOStream is created for this purpose. If + * out.get()==NULL then return.get()==NULL on return also! + * + * \relates basic_FancyOStream + */ +template +RCP > +getFancyOStream( const RCP > &out ) +{ + if(out.get()==NULL) + return Teuchos::null; + RCP > + fancyOut = rcp_dynamic_cast >(out); + if(fancyOut.get()) + return fancyOut; + return rcp(new basic_FancyOStream(out)); +} + +/** \brief Tabbing class for helping to create formated, indented output for a + * basic_FancyOStream object. + * + * Use the typedef OSStream for support for the char + * character type. + * + * This class is used to create tab indents and set line prefix names for + * output that is generated by a basic_FancyOStream object. + * + * \relates basic_FancyOStream + */ +template > +class basic_OSTab +{ +public: + + /** \brief . */ + static const int DISABLE_TABBING = -99999; // This magic number should be just fine! + /** \brief. */ + basic_OSTab( + const RCP > &fancyOStream + ,const int tabs = 1 + ,const std::basic_string linePrefix = "" + ) + :fancyOStream_(fancyOStream) + ,tabs_(tabs) + ,linePrefix_(linePrefix) + { + updateState(); + } + /** \brief. */ + basic_OSTab( + const RCP > &oStream + ,const int tabs = 1 + ,const std::basic_string linePrefix = "" + ) + :fancyOStream_(getFancyOStream(oStream)) + ,tabs_(tabs) + ,linePrefix_(linePrefix) + { + updateState(); + } + /** \brief Warning: Only call this constructor for stack-based object. */ + basic_OSTab( + basic_FancyOStream &fancyOStream + ,const int tabs = 1 + ,const std::basic_string linePrefix = "" + ) + :fancyOStream_(rcp(&fancyOStream,false)) + ,tabs_(tabs) + ,linePrefix_(linePrefix) + { + updateState(); + } + /** \brief Warning: Only call this constructor for stack-based object. */ + basic_OSTab( + std::basic_ostream &oStream + ,const int tabs = 1 + ,const std::basic_string linePrefix = "" + ) + :fancyOStream_(getFancyOStream(rcp(&oStream,false))) + ,tabs_(tabs) + ,linePrefix_(linePrefix) + { + updateState(); + } + /** \brief. */ + basic_OSTab( const basic_OSTab &osTab ) + :fancyOStream_(osTab.fancyOStream_) + ,tabs_(osTab.tabs_) + { + updateState(); + } + /** \brief. */ + ~basic_OSTab() + { + if(fancyOStream_.get()) { + if(tabs_==DISABLE_TABBING) + fancyOStream_->popDisableTabbing(); + else + fancyOStream_->popTab(); + if(linePrefix_.length()) fancyOStream_->popLinePrefix(); + } + } + /** \brief. */ + basic_OSTab& operator=( const basic_OSTab &osTab ) + { + fancyOStream_ = osTab.fancyOStream_; + tabs_ = osTab.tabs_; + updateState(); + return *this; + } + /** \brief. */ + basic_OSTab& incrTab(const int tabs = 1) + { + tabs_ += tabs; + if(fancyOStream_.get()) { + fancyOStream_->popTab(); + fancyOStream_->pushTab(tabs_); + } + return *this; + } + /** \brief. */ + basic_FancyOStream& o() const + { + return *fancyOStream_; + } + /** \brief. */ + basic_FancyOStream* get() const + { + return fancyOStream_.get(); + } + +private: + + RCP > fancyOStream_; + int tabs_; + std::basic_string linePrefix_; + + void updateState() + { + if(fancyOStream_.get()) { + if(tabs_==DISABLE_TABBING) + fancyOStream_->pushDisableTabbing(); + else + fancyOStream_->pushTab(tabs_); + if(linePrefix_.length()) fancyOStream_->pushLinePrefix(linePrefix_); + } + } + +}; + +/** \brief Create a tab for an RCP-wrapped basic_FancyOStream object + * to cause the indentation of all output automatically!. + * + * This function returns an RCP object to a basic_FancyOStream object + * that has its tab indented by one. If the input *out object is + * already a %basic_FancyOStream object, then that object is used as + * is. If the *out object is not a %basic_FancyOStream + * object, then a new %basic_FancyOStream object is created and its + * tab is set!" + * + * In any case, when the returned RCP object is destroyed, the tab will be + * removed automatically! + * + * \relates basic_FancyOStream + */ +template +RCP > +tab( + const RCP > &out + ,const int tabs = 1 + ,const std::basic_string linePrefix = "" + ) +{ + if(out.get()==NULL) + return Teuchos::null; + RCP > + fancyOut = rcp(&*out,false); + set_extra_data( out, "out", &fancyOut ); + set_extra_data( + rcp(new basic_OSTab(out,tabs,linePrefix)) + ,"OSTab" + ,&fancyOut + ,PRE_DESTROY + ); + return fancyOut; +} + + +/** \brief Create a tab for an RCP-wrapped std:: std::ostream object + * to cause the indentation of all output automatically!. + * + * This function returns an RCP object to a basic_FancyOStream object + * that has its tab indented by one. If the input *out object is + * already a %basic_FancyOStream object, then that object is used as + * is. If the *out object is not a %basic_FancyOStream + * object, then a new %basic_FancyOStream object is created and its + * tab is set!" + * + * In any case, when the returned RCP object is destroyed, the tab will be + * removed automatically! + * + * \relates basic_FancyOStream + */ +template +RCP > +tab( + const RCP > &out + ,const int tabs = 1 + ,const std::basic_string linePrefix = "" + ) +{ + return tab(getFancyOStream(out),tabs,linePrefix); +} + +// /////////////////////////////// +// Typedefs + +/** \brief . + * \ingroup teuchos_outputting_grp + */ +typedef basic_FancyOStream FancyOStream; + +/** \brief . + * \ingroup teuchos_outputting_grp + */ +typedef basic_OSTab OSTab; + +/** \brief . + * \ingroup teuchos_outputting_grp + */ +#define TEUCHOS_OSTAB ::Teuchos::OSTab __localThisTab = this->getOSTab() + +// //////////////////////////////// +// Defintions + +// +// basic_FancyOStream_buf +// + +template +basic_FancyOStream_buf::basic_FancyOStream_buf( + const RCP > &oStream + ,const std::basic_string &tabIndentStr + ,const int startingTab + ,const bool showLinePrefix + ,const int maxLenLinePrefix + ,const bool showTabCount + ,const bool showProcRank + ) +{ + this->initialize(oStream,tabIndentStr,startingTab,showLinePrefix, + maxLenLinePrefix,showTabCount,showProcRank); +} + +template +void basic_FancyOStream_buf::initialize( + const RCP > &oStream + ,const std::basic_string &tabIndentStr + ,const int startingTab + ,const bool showLinePrefix + ,const int maxLenLinePrefix + ,const bool showTabCount + ,const bool showProcRank + ) +{ + oStreamSet_ = oStream; + oStream_ = oStream; + tabIndentStr_ = tabIndentStr; + showLinePrefix_ = showLinePrefix; + maxLenLinePrefix_ = maxLenLinePrefix; + showTabCount_ = showTabCount; + showProcRank_ = showProcRank; + rootRank_ = -1; + procRank_ = GlobalMPISession::getRank(); + numProcs_ = GlobalMPISession::getNProc(); + rankPrintWidth_ = int(std::log10(float(numProcs_)))+1; + tabIndent_ = startingTab; + tabIndentStack_.clear(); + linePrefixStack_.clear(); + wroteNewline_ = true; + enableTabbingStack_ = 0; +} + +template +RCP > +basic_FancyOStream_buf::getOStream() +{ + return oStreamSet_; +} + +template +void basic_FancyOStream_buf::setTabIndentStr( + const std::basic_string &tabIndentStr + ) +{ + tabIndentStr_ = tabIndentStr; +} + +template +const std::basic_string& +basic_FancyOStream_buf::getTabIndentStr() const +{ + return tabIndentStr_; +} + +template +void basic_FancyOStream_buf::setShowLinePrefix(const bool showLinePrefix) +{ + showLinePrefix_ = showLinePrefix; +} + +template +bool basic_FancyOStream_buf::getShowLinePrefix() const +{ + return showLinePrefix_; +} + +template +void basic_FancyOStream_buf::setMaxLenLinePrefix(const int maxLenLinePrefix) +{ + TEST_FOR_EXCEPT( !(maxLenLinePrefix>=5) ); + maxLenLinePrefix_ = maxLenLinePrefix; +} + +template +int basic_FancyOStream_buf::getMaxLenLinePrefix() const +{ + return maxLenLinePrefix_; +} + +template +void basic_FancyOStream_buf::setShowTabCount(const bool showTabCount) +{ + showTabCount_ = showTabCount; +} + +template +bool basic_FancyOStream_buf::getShowTabCount() const +{ + return showTabCount_; +} + +template +void basic_FancyOStream_buf::setShowProcRank(const bool showProcRank) +{ + showProcRank_ = showProcRank; +} + +template +bool basic_FancyOStream_buf::getShowProcRank() const +{ + return showProcRank_; +} + +template +void basic_FancyOStream_buf::setProcRankAndSize( + const int procRank, const int numProcs + ) +{ + procRank_ = procRank; + numProcs_ = numProcs; +} + +template +int basic_FancyOStream_buf::getProcRank() const +{ + return procRank_; +} + +template +int basic_FancyOStream_buf::getNumProcs() const +{ + return numProcs_; +} + +template +void basic_FancyOStream_buf::setOutputToRootOnly( + const int rootRank + ) +{ + rootRank_ = rootRank; + if(rootRank >= 0) { + if(rootRank == procRank_) + oStream_ = oStreamSet_; + else + oStream_ = rcp(new oblackholestream()); + // Only processor is being output to so there is no need for line + // batching! + lineOut_ = null; + } + else { + oStream_ = oStreamSet_; + // Output is being sent to all processors so we need line batching to + // insure that each line will be printed all together! + lineOut_ = rcp(new std::ostringstream()); + } +} + +template +int basic_FancyOStream_buf::getOutputToRootOnly() const +{ + return rootRank_; +} + +template +void basic_FancyOStream_buf::pushTab(const int tabs) +{ + if( tabIndent_ + tabs < 0 ) { + tabIndentStack_.push_back(-tabIndent_); + tabIndent_ = 0; + } + else { + tabIndentStack_.push_back(tabs); + tabIndent_ += tabs; + } +} + +template +int basic_FancyOStream_buf::getNumCurrTabs() const +{ + return tabIndent_; +} + +template +void basic_FancyOStream_buf::popTab() +{ + tabIndent_ -= tabIndentStack_.back(); + tabIndentStack_.pop_back(); +} + +template +void basic_FancyOStream_buf::pushLinePrefix( + const std::basic_string &linePrefix + ) +{ + linePrefixStack_.push_back(linePrefix); +} + +template +void basic_FancyOStream_buf::popLinePrefix() +{ + linePrefixStack_.pop_back(); +} + +template +const std::basic_string& +basic_FancyOStream_buf::getTopLinePrefix() const +{ + return linePrefixStack_.back(); +} + +template +void basic_FancyOStream_buf::pushDisableTabbing() +{ + ++enableTabbingStack_; +} + +template +void basic_FancyOStream_buf::popDisableTabbing() +{ + --enableTabbingStack_; +} + +// protected + +template +std::streamsize basic_FancyOStream_buf::xsputn( + const char_type* s, std::streamsize n + ) +{ +#ifdef TEUCHOS_FANCY_OSTREAM_SHOW_ALL_CALLS + std::cerr << "\ncalled xsputn()\n"; +#endif + writeChars(s,n); + return n; +} + +template +typename basic_FancyOStream_buf::int_type +basic_FancyOStream_buf::overflow(int_type c) +{ +#ifdef TEUCHOS_FANCY_OSTREAM_SHOW_ALL_CALLS + std::cerr << "\ncalled overflow()\n"; +#endif + if(c != traits_type::eof()) { + const char_type cc[] = { traits_type::to_char_type(c) }; + this->writeChars(cc,1); + } + return traits_type::not_eof(c); + //return std::basic_streambuf::overflow(c); +} + +// private + +template +std::ostream& basic_FancyOStream_buf::out() +{ + if(lineOut_.get()) + return *lineOut_; + return *oStream_; +} + +template +void basic_FancyOStream_buf::writeChars( + const char_type s[], std::streamsize n + ) +{ + if(n == 0) return; + std::streamsize p = 0, first_p = 0; + bool done_outputting = false; + const char_type newline = '\n'; + while( !done_outputting ) { + // Find the next newline + for( p = first_p; p < n; ++p ) { + if(s[p] == newline) { + break; + } + } + if(p == n) { + // We did not find a newline at the end! + --p; + done_outputting = true; + } + else if( p == n-1 && s[p] == newline ) { + // The last character in the std::string is a newline + done_outputting = true; + } + // Write the beginning of the line if we need to + if(wroteNewline_) { + writeFrontMatter(); + wroteNewline_ = false; + } + // Write up to the newline or the end of the std::string + out().write(s+first_p,p-first_p+1); + if(s[p] == newline) { + wroteNewline_ = true; + if(lineOut_.get()) { + *oStream_ << lineOut_->str() << std::flush; + lineOut_->str(""); + } + } + // Update for next search + if(!done_outputting) + first_p = p+1; + } +} + +template +void basic_FancyOStream_buf::writeFrontMatter() +{ + bool didOutput = false; + std::ostream &out = this->out(); + if(showProcRank_) { + out << "p=" << std::right << std::setw(rankPrintWidth_) << procRank_; + didOutput = true; + } + if(showLinePrefix_) { + if(didOutput) + out << ", "; + std::string currLinePrefix = ""; + if ( linePrefixStack_.size() ) + currLinePrefix = this->getTopLinePrefix(); + const int localMaxLenLinePrefix = + TEUCHOS_MAX( as(currLinePrefix.length()), maxLenLinePrefix_ ); + out << std::left << std::setw(localMaxLenLinePrefix); + out << currLinePrefix; + didOutput = true; + } + if(showTabCount_) { + if(didOutput) + out << ", "; + out << "tabs=" << std::right << std::setw(2) << tabIndent_; + didOutput = true; + } + // ToDo: Add the Prefix name if asked + // ToDo: Add the processor number if asked + // ToDo: Add the number of indents if asked + if(didOutput) { + out << " |" << tabIndentStr_; + } + if(enableTabbingStack_==0) { + for( int i = 0; i < tabIndent_; ++i ) + out << tabIndentStr_; + } +} + +// +// basic_FancyOStream +// + +template +basic_FancyOStream::basic_FancyOStream( + const RCP< std::basic_ostream > &oStream + ,const std::basic_string &tabIndentStr + ,const int startingTab + ,const bool showLinePrefix + ,const int maxLenLinePrefix + ,const bool showTabCount + ,const bool showProcRank + ) + :ostream_t(NULL), + streambuf_(oStream,tabIndentStr,startingTab,showLinePrefix, + maxLenLinePrefix,showTabCount,showProcRank) +{ + this->init(&streambuf_); +} + +template +void basic_FancyOStream::initialize( + const RCP< std::basic_ostream > &oStream + ,const std::basic_string &tabIndentStr + ,const int startingTab + ,const bool showLinePrefix + ,const int maxLenLinePrefix + ,const bool showTabCount + ,const bool showProcRank + ) +{ + streambuf_.initialize(oStream,tabIndentStr,startingTab, + showLinePrefix,maxLenLinePrefix,showTabCount,showProcRank); + this->init(&streambuf_); +} + +template +RCP > +basic_FancyOStream::getOStream() +{ + return streambuf_.getOStream(); +} + +template +basic_FancyOStream& +basic_FancyOStream::setTabIndentStr( + const std::basic_string &tabIndentStr + ) +{ + streambuf_.setTabIndentStr(tabIndentStr); + return *this; +} + +template +const std::basic_string& +basic_FancyOStream::getTabIndentStr() const +{ + return streambuf_.getTabIndentStr(); +} + +template +basic_FancyOStream& +basic_FancyOStream::setShowAllFrontMatter( + const bool showAllFrontMatter + ) +{ + streambuf_.setShowLinePrefix(showAllFrontMatter); + streambuf_.setShowTabCount(showAllFrontMatter); + streambuf_.setShowProcRank(showAllFrontMatter); + return *this; +} + +template +basic_FancyOStream& +basic_FancyOStream::setShowLinePrefix(const bool showLinePrefix) +{ + streambuf_.setShowLinePrefix(showLinePrefix); + return *this; +} + +template +basic_FancyOStream& +basic_FancyOStream::setMaxLenLinePrefix(const int maxLenLinePrefix) +{ + streambuf_.setMaxLenLinePrefix(maxLenLinePrefix); + return *this; +} + +template +basic_FancyOStream& +basic_FancyOStream::setShowTabCount(const bool showTabCount) +{ + streambuf_.setShowTabCount(showTabCount); + return *this; +} + +template +basic_FancyOStream& +basic_FancyOStream::setShowProcRank(const bool showProcRank) +{ + streambuf_.setShowProcRank(showProcRank); + return *this; +} + +template +basic_FancyOStream& +basic_FancyOStream::setProcRankAndSize( const int procRank, const int numProcs ) +{ + streambuf_.setProcRankAndSize(procRank,numProcs); + return *this; +} + +template +basic_FancyOStream& +basic_FancyOStream::setOutputToRootOnly( const int rootRank ) +{ + streambuf_.setOutputToRootOnly(rootRank); + return *this; +} + +template +int basic_FancyOStream::getOutputToRootOnly() const +{ + return streambuf_.getOutputToRootOnly(); +} + +template +void basic_FancyOStream::copyAllOutputOptions( const basic_FancyOStream &oStream ) +{ + //streambuf_.setTabIndentStr(oStream.streambuf_.getTabIndentStr()); + streambuf_.setShowLinePrefix(oStream.streambuf_.getShowLinePrefix()); + streambuf_.setMaxLenLinePrefix(oStream.streambuf_.getMaxLenLinePrefix()); + streambuf_.setShowTabCount(oStream.streambuf_.getShowTabCount()); + streambuf_.setShowProcRank(oStream.streambuf_.getShowProcRank()); + streambuf_.setProcRankAndSize(oStream.streambuf_.getProcRank(),oStream.streambuf_.getNumProcs()); + streambuf_.setOutputToRootOnly(oStream.streambuf_.getOutputToRootOnly()); +} + +template +void basic_FancyOStream::pushTab(const int tabs) +{ + streambuf_.pushTab(tabs); +} + +template +int basic_FancyOStream::getNumCurrTabs() const +{ + return streambuf_.getNumCurrTabs(); +} + +template +void basic_FancyOStream::popTab() +{ + streambuf_.popTab(); +} + +template +void basic_FancyOStream::pushLinePrefix( + const std::basic_string &linePrefix + ) +{ + streambuf_.pushLinePrefix(linePrefix); +} + +template +void basic_FancyOStream::popLinePrefix() +{ + streambuf_.popLinePrefix(); +} + +template +const std::basic_string& +basic_FancyOStream::getTopLinePrefix() const +{ + return streambuf_.getTopLinePrefix(); +} + +template +void basic_FancyOStream::pushDisableTabbing() +{ + streambuf_.pushDisableTabbing(); +} + +template +void basic_FancyOStream::popDisableTabbing() +{ + return streambuf_.popDisableTabbing(); +} + +} // namespace Teuchos + +#endif // TEUCHOS_FANCY_O_STREAM_HPP diff --git a/fastlib/trilinos/include/Teuchos_FileInputSource.hpp b/fastlib/trilinos/include/Teuchos_FileInputSource.hpp new file mode 100644 index 0000000000..48fb65a8e0 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_FileInputSource.hpp @@ -0,0 +1,63 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef Teuchos_FILEINPUTSOURCE_H +#define Teuchos_FILEINPUTSOURCE_H + +/*! \file Teuchos_FileInputSource.hpp + \brief Definition of XMLInputSource derived class for reading XML from a file +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_XMLInputSource.hpp" + + +namespace Teuchos +{ + /** \ingroup XML + * \brief Instantiation of XMLInputSource class for reading XML from a file. + */ + class FileInputSource : public XMLInputSource + { + public: + /** \brief Constructor */ + FileInputSource(const std::string& filename); + + /** \brief Destructor */ + virtual ~FileInputSource(){;} + + /** \brief Create a FileInputStream */ + virtual RCP stream() const; + + private: + std::string filename_; + }; + +} +#endif + diff --git a/fastlib/trilinos/include/Teuchos_FileInputStream.hpp b/fastlib/trilinos/include/Teuchos_FileInputStream.hpp new file mode 100644 index 0000000000..bc1f8e67cc --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_FileInputStream.hpp @@ -0,0 +1,66 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_FILEINPUTSTREAM_H +#define TEUCHOS_FILEINPUTSTREAM_H + +/*! \file Teuchos_FileInputStream.hpp + \brief Definition of XMLInputStream derived class for reading XML from a file +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_XMLInputStream.hpp" + +namespace Teuchos +{ + using std::string; + + /** \ingroup XML + * \brief Instantiation of XMLInputStream class for reading an entire document from a file. + * \note This is a low-level object and should not be needed at the user level. + * FileInputSource is the user-level object. + */ + class FileInputStream : public XMLInputStream + { + public: + /** \brief Construct with a filename */ + FileInputStream(const std::string& filename); + + /** \brief Destructor */ + virtual ~FileInputStream() { if( file_ ) { std::fclose(file_); } } + + /** \brief Read up to maxToRead bytes */ + virtual unsigned int readBytes(unsigned char* const toFill, + const unsigned int maxToRead); + + private: + std::FILE* file_; + }; +} +#endif + diff --git a/fastlib/trilinos/include/Teuchos_Flops.hpp b/fastlib/trilinos/include/Teuchos_Flops.hpp new file mode 100644 index 0000000000..6d8b0ea402 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Flops.hpp @@ -0,0 +1,125 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef TEUCHOS_FLOPS_HPP +#define TEUCHOS_FLOPS_HPP + +/*! \file Teuchos_Flops.hpp + \brief Object for providing basic support and consistent interfaces for + counting/reporting floating-point operations performed in Teuchos computational + classes. +*/ + +/*! \class Teuchos::Flops + \brief The Teuchos Floating Point Operations Class. + + The Teuchos_Flops class provides basic support and consistent interfaces + for counting and reporting floating point operations performed in + the Teuchos computational classes. All classes based on the Teuchos::CompObject + can count flops by the user creating an Teuchos::Flops object and calling the SetFlopCounter() + method for an Teuchos_CompObject. +*/ + +namespace Teuchos +{ +class Flops +{ + public: + + //! @name Constructor/Destructor. + //@{ + + //! Default Constructor. + /*! Creates a Flops instance. This instance can be queried for + the number of floating point operations performed for the associated + \e this object. + */ + Flops(); + + //! Copy Constructor. + /*! Makes an exact copy of an existing Flops instance. + */ + Flops(const Flops &flops); + + //! Destructor. + /*! Completely deletes a Flops object. + */ + virtual ~Flops(); + + //@} + + //! @name Accessor methods. + //@{ + + //! Returns the number of floating point operations with \e this object and resets the count. + double flops() const { return flops_; } + + //@} + + //! @name Reset methods. + //@{ + + //! Resets the number of floating point operations to zero for \e this multi-std::vector. + void resetFlops() {flops_ = 0.0;} + + //@} + + friend class CompObject; + + protected: + + mutable double flops_; + + //! @name Updating methods. + //@{ + //! Increment Flop count for \e this object from an int + void updateFlops(int addflops) const {flops_ += (double) addflops; } + + //! Increment Flop count for \e this object from a long int + void updateFlops(long int addflops) const {flops_ += (double) addflops; } + + //! Increment Flop count for \e this object from a double + void updateFlops(double addflops) const {flops_ += (double) addflops; } + + //! Increment Flop count for \e this object from a float + void updateFlops(float addflops) const {flops_ += (double) addflops; } + + //@} + + private: + +}; + + // #include "Teuchos_Flops.cpp" + +} // namespace Teuchos + +#endif // end of TEUCHOS_FLOPS_HPP diff --git a/fastlib/trilinos/include/Teuchos_GlobalMPISession.hpp b/fastlib/trilinos/include/Teuchos_GlobalMPISession.hpp new file mode 100644 index 0000000000..67bce82451 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_GlobalMPISession.hpp @@ -0,0 +1,128 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_GLOBAL_MPI_SESSION_HPP +#define TEUCHOS_GLOBAL_MPI_SESSION_HPP + +/*! \file Teuchos_MPISession.hpp + \brief A MPI utilities class, providing methods for initializing, + finalizing, and querying the global MPI session +*/ +#include "Teuchos_ConfigDefs.hpp" + +#ifdef HAVE_MPI +#include "mpi.h" +#endif + +namespace Teuchos { + +/** \brief This class provides methods for initializing, finalizing, and + * querying the global MPI session. + * + * This class is primarilly designed to insulate basic main() + * program type of code from having to know if MPI is enabled or not. + * + * ToDo: Give examples! + */ +class GlobalMPISession +{ +public: + + //! @name Public constructor and destructor + //@{ + + /** \brief Calls MPI_Init() if MPI is enabled. + * + * \param argc [in] Argment passed into main(argc,argv) + * \param argv [in] Argment passed into main(argc,argv) + * \param out [in] If out!=NULL, then a small message on each + * processor will be printed to this stream. The default is &std::cout. + * + * If the option --teuchos-suppress-startup-banner is found, the + * this option will be removed from argv[] before being passed to + * MPI_Init(...) and the startup output message to *out + * will be suppressed. + * + * Warning! This constructor can only be called once per + * executable or an error is printed to *out and an std::exception will + * be thrown! + */ + GlobalMPISession( int* argc, char*** argv, std::ostream *out = &std::cout ); + + /** \brief Calls MPI_Finalize() if MPI is enabled. + */ + ~GlobalMPISession(); + + //@} + + //! @name Static functions + //@{ + + /** \breif Return if MPI is initialized or not. */ + static bool mpiIsInitialized(); + + /** \breif Return if MPI has already been finalized. */ + static bool mpiIsFinalized(); + + /** \brief Returns the process rank relative to MPI_COMM_WORLD + * + * Returns 0 if MPI is not enabled. + * + * Note, this function can be called even if the above constructor was never + * called so it is safe to use no matter how MPI_Init() got called + * (but it must have been called somewhere). + */ + static int getRank(); + + /** \brief Returns the number of processors relative to + * MPI_COMM_WORLD + * + * Returns 1 if MPI is not enabled. + * + * Note, this function can be called even if the above constructor was never + * called so it is safe to use no matter how MPI_Init() got called + * (but it must have been called somewhere). + */ + static int getNProc(); + + //@} + +private: + + static bool haveMPIState_; + static bool mpiIsFinalized_; + static int rank_; + static int nProc_; + + static void initialize( std::ostream *out ); + +}; + +} // namespace Teuchos + +#endif // TEUCHOS_GLOBAL_MPI_SESSION_HPP diff --git a/fastlib/trilinos/include/Teuchos_Handle.hpp b/fastlib/trilinos/include/Teuchos_Handle.hpp new file mode 100644 index 0000000000..adecf6e37f --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Handle.hpp @@ -0,0 +1,187 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_HANDLE_HPP +#define TEUCHOS_HANDLE_HPP + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_Describable.hpp" +#include "Teuchos_Handleable.hpp" + +namespace Teuchos +{ + + /** \brief Templated handle class with strong const protection. + * + * In writing derived types, it is usually simplest to use the + * TEUCHOS_CONST_HANDLE_CTORS macro to generate boilerplate constructor + * code. + * + * There are two modes of construction: + * construction from an existing RCP, + * \code + * RCP r = rcp(new Derived(blahblah)); + * ConstHandle h = r; + * \endcode + * and construction from a raw pointer, + * \code + * ConstHandle h = new Derived(blahblah); + * \endcode + * The second form makes the code slightly cleaner. Note that to use this + * second form, it is necessary that Derived implement the ConstHandleable + * interface; this is necessary to avoid any implicit conversions from just + * any raw pointer to a smart pointer. + * + * Note that the first form with rcp() must be used whenever the object + * being handled has been allocated on the stack (using rcp(ptr,false) of + * course). + */ + template + class ConstHandle : public virtual Describable + { + public: + /** \brief Construct with an existing RCP. */ + ConstHandle(const RCP& ptr) : ptr_(ptr) {;} + /** \brief Construct with a raw pointer to a ConstHandleable. This will make + * a call to rcp(), thus removing that call from the user interface. */ + explicit ConstHandle(const ConstHandleable* ptr) : ptr_(ptr->getConstRcp()) {;} + /** \brief Read-only access to the underlying smart pointer. */ + const RCP& constPtr() const {return ptr_;} + /** \brief Access to raw pointer */ + const PointerType * const rawPtr() {return this->constPtr().get();} + protected: + /** \brief The empty ctor will only be called by Handle ctors */ + explicit ConstHandle() : ptr_() {;} + /** \brief This function is needed in Handle ctors. + * + * The Handle ctors call the empty ConstHandle ctor and then set the + * pointer in the ConstHandle with a call to setRcp(). */ + void setRcp(const RCP& ptr) + {ptr_=rcp_const_cast(ptr);} + /** \brief Protected non-const access to the underlying smart pointer. + * + * This will be called by the nonConstPtr() method of the non-const Handle + * subclass */ + RCP nonConstPtr() const + {return rcp_const_cast(ptr_);} + private: + /** \brief . */ + RCP ptr_; + }; + + /** \brief Generic templated handle class. + * + * In writing derived types, it is usually simplest to use the + * TEUCHOS_HANDLE_CTORS macro to generate boilerplate constructor code. + * + * There are two modes of construction: + * construction from an existing RCP, + * \code + * RCP r = rcp(new Derived(blahblah)); + * Handle h = r; + * \endcode + * and construction from a raw pointer, + * \code + * Handle h = new Derived(blahblah); + * \endcode + * The second form makes the code slightly cleaner. + * Note that to use this second form, it is necessary that Derived implement the + * Handleable interface; this is necessary to avoid any implicit conversions + * from raw pointers to smart pointers. + * + * Note that the first form must be used whenever the object being handled has + * been allocated on the stack. + */ + template + class Handle : public virtual ConstHandle + { + public: + /** \brief . */ + Handle() + : ConstHandle() {} + /** \brief Construct with an existing RCP */ + Handle(const RCP& smartPtr) + : ConstHandle() + { + /* \brief We need to set the rcp in the base class */ + setRcp(smartPtr); + } + /** \brief Construct with a raw pointer to a Handleable. + * + * This will make a call to rcp() internally, thus removing that call from the + * user interface. + */ + explicit Handle(Handleable* rawPtr) + : ConstHandle() + { + /* \brief We need to set the rcp in the base class. */ + setRcp(rawPtr->getRcp()); + } + /** \brief Read/write access to the underlying smart pointer. + */ + RCP ptr() const {return this->nonConstPtr();} + /** \brief Access to non-const raw pointer. */ + PointerType* rawPtr() const {return this->nonConstPtr().get();} + }; + +} // namespace Teuchos + +/** \brief This helper macro defines boilerplate constructors for classes + * deriving from Handle. + * + * If class MyHandle is a handle to a type MyType, simply + * put + * \code + * TEUCHOS_HANDLE_CTORS(MyHandle, MyType); + * \endcode + * in the class declaration of MyHandle and the macro will create + * an empty ctor, a ctor from a smart ptr, and a ctor from a raw pointer. + * The macro will also create appropriate doxygen for the handle ctors */ +#define TEUCHOS_HANDLE_CTORS(handle, contents) \ +handle() : Teuchos::Handle() {;} \ +handle(Teuchos::Handleable* rawPtr) : Teuchos::Handle(rawPtr) {;} \ +handle(const Teuchos::RCP& smartPtr) : Teuchos::Handle(smartPtr){;} + +/** \brief. This helper macro defines boilerplate constructors for classes + * deriving from ConstHandle. + * + * If class MyHandle is a const handle to a type MyType, simply + * put + * \code + * TEUCHOS_CONST_HANDLE_CTORS(MyHandle, MyType); + * \endcode + * in the class declaration of MyHandle and the macro will create + * an empty ctor, a ctor from a smart ptr, and a ctor from a raw pointer. + * The macro will also create appropriate doxygen for the handle ctors */ +#define TEUCHOS_CONST_HANDLE_CTORS(handle, contents) \ +handle( Teuchos::ENull _null = Teuchos::null ) : Teuchos::ConstHandle() {;} \ +handle(const Teuchos::ConstHandleable* rawPtr) : Teuchos::ConstHandle(rawPtr) {;} \ +handle(const Teuchos::RCP& smartPtr) : Teuchos::ConstHandle(smartPtr){;} + +#endif // TEUCHOS_CONSTHANDLE_HPP diff --git a/fastlib/trilinos/include/Teuchos_Handleable.hpp b/fastlib/trilinos/include/Teuchos_Handleable.hpp new file mode 100644 index 0000000000..92187d83bb --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Handleable.hpp @@ -0,0 +1,127 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_HANDLEABLE_HPP +#define TEUCHOS_HANDLEABLE_HPP + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_RCP.hpp" + + +namespace Teuchos +{ + /** \brief Class ConstHandleable provides an abstract interface for + * polymorphic conversion from raw pointers to const smart pointers. + * + * Recall from the Teuchos RCP documentation that one should never + * create directly a smart pointer from a raw pointer; rather, smart + * pointers should be created through a call to rcp(). The type of the + * argument to rcp() must be known at compile time. This makes the syntax + * \code ConstHandle h = new Derived(); \endcode impossible with the + * straightforward implementation in which ConstHandle takes a raw pointer + * to a Base. In order to preserve this clean syntax, we require any handles + * supporting this syntax to take a raw pointer to a ConstHandleable, + * where ConstHandleable provides a getConstRcp() method which returns + * the result of a call to rcp() on this. + */ + template + class ConstHandleable + { + public: + /** \brief . */ + virtual ~ConstHandleable(){} + + /** \brief Virtual dtorReturn a safely-created RCP to the base + * type */ + virtual RCP getConstRcp() const = 0 ; + }; + + /** \brief Class Handleable provides an abstract interface for polymorphic + * conversion from raw pointers to smart pointers. + * + * Recall from the Teuchos RCP documentation that one should never + * create directly a smart pointer from a raw pointer; rather, smart + * pointers should be created through a call to rcp(). The type of the + * argument to rcp() must be known at compile time. This makes the syntax + * \code Handle h = new Derived(); \endcode impossible with the + * straightforward implementation in which Handle takes a raw pointer to a + * Base. In order to preserve this clean syntax, we require any handles + * supporting this syntax to take a raw pointer to a Handleable, where + * Handleable provides a getRcp() method which returns the result of a + * call to rcp() on this. + */ + template + class Handleable : public virtual ConstHandleable + { + public: + + /** \brief . */ + virtual ~Handleable(){;} + + /** \brief Return a safely-created RCP to the base type */ + virtual RCP getRcp() = 0 ; + + }; +} + + +/** \brief Use this macro as an easy way to implement the Handleable interface + * in a derived class. + * + * For example, + * + * \code + * class Derived : public Handleable + * { + * public: + * TEUCHOS_GET_RCP(Base); + * }; + * \endcode + */ +#define TEUCHOS_GET_RCP(Base) \ + virtual Teuchos::RCP getConstRcp() const {return rcp(this);} \ + virtual Teuchos::RCP getRcp() {return rcp(this);} + +/** \brief Use this macro as an easy way to implement the ConstHandleable + * interface in a derived class. For example, + * + * \code + * class Derived : public ConstHandleable + * { + * public: + * TEUCHOS_GET_CONST_RCP(Base); + * }; + * \endcode + */ +#define TEUCHOS_GET_CONST_RCP(Base) \ +virtual Teuchos::RCP getConstRcp() const {return rcp(this);} + + + + +#endif // TEUCHOS_HANDLEABLE_HPP diff --git a/fastlib/trilinos/include/Teuchos_HashSet.hpp b/fastlib/trilinos/include/Teuchos_HashSet.hpp new file mode 100644 index 0000000000..19e44f8c98 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_HashSet.hpp @@ -0,0 +1,263 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_HASHSET_H +#define TEUCHOS_HASHSET_H + +/*! \file Teuchos_HashSet.hpp + \brief Templated hashtable-based set +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_HashUtils.hpp" + +namespace Teuchos +{ + using std::string; + + + /** \ingroup Containers + * \brief Templated hashtable-based set. + + HashSet is a hashtable-based set, similar to the STL set class + * or the Java HashSet class. + */ + template class HashSet + { + public: + + //! Create an empty HashSet + inline HashSet(int capacity=19); + + //! Check for the presence of a key + inline bool containsKey(const Key& key) const ; + + //! Put a new object into the table. + inline void put(const Key& key); + + //! Remove from the table the element given by key. + inline void remove(const Key& key); + + //! Get the number of elements in the table + inline int size() const {return count_;} + + //! Get list of keys in Array form + inline Array arrayify() const ; + + //! Get list of keys in Array form + inline void arrayify(Array& keys) const ; + + //! Write to a std::string + inline std::string toString() const ; + + private: + /** rebuild the hashtable when the size has changed */ + inline void rehash(); + /** get the next prime number near a given capacity */ + inline int nextPrime(int newCap) const ; + + Array > data_; + int count_; + int capacity_; + mutable Key mostRecentKey_; + }; + + + /** \relates HashSet + \brief Write HashSet to a stream + */ + template + std::ostream& operator<<(std::ostream& os, const HashSet& h); + + template inline + std::string toString(const HashSet& h) {return h.toString();} + + + template inline + HashSet::HashSet(int capacity) + : data_(), count_(0), capacity_(HashUtils::nextPrime(capacity)) + { + data_.resize(capacity_); + } + + template inline + bool HashSet::containsKey(const Key& key) const + { + const Array& candidates + = data_[hashCode(key) % capacity_]; + + for (int i=0; i inline + void HashSet::put(const Key& key) + { + int index = hashCode(key) % capacity_; + + Array& local = data_[index]; + + // check for duplicate key + for (int i=0; i capacity_) + { + capacity_ = HashUtils::nextPrime(capacity_+1); + rehash(); + // recaluate index + index = hashCode(key) % capacity_; + } + + data_[index].append(key); + } + + + + template inline + void HashSet::rehash() + { + Array > tmp(capacity_); + + for (int i=0; i inline + Array HashSet::arrayify() const + { + Array rtn; + rtn.reserve(size()); + + for (int i=0; i inline + void HashSet::arrayify(Array& rtn) const + { + rtn.resize(0); + + for (int i=0; i inline + std::string HashSet::toString() const + { + std::string rtn = "HashSet["; + + bool first = true; + + for (int i=0; i inline + void HashSet::remove(const Key& key) + { + TEST_FOR_EXCEPTION(!containsKey(key), + std::runtime_error, + "HashSet::remove: key " + << Teuchos::toString(key) + << " not found in HashSet" + << toString()); + + count_--; + int h = hashCode(key) % capacity_; + Array& candidates = data_[h]; + + for (int i=0; i inline + std::ostream& operator<<(std::ostream& os, const HashSet& h) + { + return os << h.toString(); + } + + +} + +#endif // TEUCHOS_HASHSET_H diff --git a/fastlib/trilinos/include/Teuchos_HashUtils.hpp b/fastlib/trilinos/include/Teuchos_HashUtils.hpp new file mode 100644 index 0000000000..17296a6314 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_HashUtils.hpp @@ -0,0 +1,121 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_HASHUTILS_H +#define TEUCHOS_HASHUTILS_H + +/*! \file Teuchos_HashUtils.hpp + \brief Utilities for generating hashcodes +*/ + +#include "Teuchos_ConfigDefs.hpp" + +namespace Teuchos +{ + using std::string; + + /** + * \ingroup Containers + * \brief Utilities for generating hashcodes. + */ + + class HashUtils + { + public: + /* Get the next prime in a sequence of hashtable sizes */ + static int nextPrime(int newCapacity); + + private: + + // sequence of primes generated via mathematica: + // Table[Prime[Round[1.5^x]], {x, 8, 36}] + static const int primeCount_; + static const int primes_[]; + /*={101, 163, 271, 443, 733, 1187, 1907, 3061, + 4919, 7759, 12379, 19543, 30841, 48487, 75989, + 119089, 185971, 290347, 452027, 703657, 1093237, + 1695781, 2627993, 4067599, 6290467, 9718019, + 15000607, 23133937, 35650091};*/ + }; + + /** \relates HashUtils + \brief Standard interface for getting the hash code of an object + */ + template int hashCode(const T& x); + + /** \relates HashUtils + \brief Get the hash code of an int + */ + template <> inline int hashCode(const int& x) + { + return x; + } + + /** \relates HashUtils + \brief Get the hash code of a double + */ + template <> inline int hashCode(const double& x) + { + return (int) x; + } + + /** \relates HashUtils + \brief Get the hash code of a bool + */ + template <> inline int hashCode(const bool& x) + { + return (int) x; + } + + + /** \relates HashUtils + \brief Get the hash code of a std::string + */ + template <> inline int hashCode(const std::string& x) + { + const char* str = x.c_str(); + int len = x.length(); + int step = len/4 + 1; + int base = 1; + int rtn = 0; + + for (int i=0; i pair. + */ + template class HashPair + { + public: + //! Empty constructor + inline HashPair() : key_(), value_() {;} + //! Basic constructor + inline HashPair(const Key& key, const Value& value) + : key_(key), value_(value) {;} + + //! Templated key variable + Key key_; + //! Templated value variable + Value value_; + }; + + /** + \ingroup Containers + \brief Templated hashtable class. + @author Kevin Long + */ + template class Hashtable + { + public: + + //! Create an empty Hashtable + inline Hashtable(int capacity=101, double rehashDensity = 0.8); + + //! Check for the presence of a key + inline bool containsKey(const Key& key) const ; + + //! Get the value indexed by key + inline const Value& get(const Key& key) const ; + + //! Put a new (key, value) pair in the table. + inline void put(const Key& key, const Value& value); + + //! Remove from the table the element given by key. + inline void remove(const Key& key); + + //! Get the number of elements in the table + inline int size() const {return count_;} + + //! Get lists of keys and values in Array form + inline void arrayify(Array& keys, Array& values) const ; + + //! Return the average degeneracy (average number of entries per hash code). + inline double avgDegeneracy() const {return avgDegeneracy_;} + + //! Return the density of the hashtable (num entries / capacity) + inline double density() const {return ((double)count_)/((double) capacity_);} + + //! Set the density at which to do a rehash + inline void setRehashDensity(double rehashDensity); + + //! Write to a std::string + inline std::string toString() const ; + + private: + + inline void rehash(); + inline int nextPrime(int newCap) const ; + inline void accumulateAvgFill(int n) const ; + + + Array > > data_; + int count_; + int capacity_; + mutable Value mostRecentValue_; + mutable Key mostRecentKey_; + + mutable int nHits_; + mutable double avgDegeneracy_; + double rehashDensity_; + }; + + template + std::string toString(const Hashtable& h); + + /** \relates Hashtable + \brief Write Hashtable to a stream + */ + template + std::ostream& operator<<(std::ostream& os, const Hashtable& h); + + template inline + Hashtable::Hashtable(int capacity, double rehashDensity) + : data_(), count_(0), capacity_(HashUtils::nextPrime(capacity)), + nHits_(0), avgDegeneracy_(0), rehashDensity_(rehashDensity) + { + data_.resize(capacity_); + } + + template inline + bool Hashtable::containsKey(const Key& key) const + { + const Array >& candidates + = data_[hashCode(key) % capacity_]; + + for (int i=0; i& c = candidates[i]; + if (c.key_ == key) + { + // (Key&) mostRecentKey_ = key; + //(Value&) mostRecentValue_ = c.value_; + return true; + } + } + return false; + } + + template inline + void Hashtable::put(const Key& key, const Value& value) + { + int index = hashCode(key) % capacity_; + + Array >& local = data_[index]; + + // check for duplicate key + for (int i=0; i rehashDensity_ * (double) capacity_) + { + capacity_ = HashUtils::nextPrime(capacity_+1); + rehash(); + // recaluate index + index = hashCode(key) % capacity_; + } + + data_[index].append(HashPair(key, value)); + } + + + + template inline + void Hashtable::rehash() + { + Array > > tmp(capacity_); + + for (int i=0; i inline + void Hashtable::arrayify(Array& keys, Array& values) const + { + keys.reserve(size()); + values.reserve(size()); + + for (int i=0; i inline + std::string Hashtable::toString() const + { + Array keys; + Array values; + arrayify(keys, values); + + std::string rtn = "["; + for (int i=0; i inline + std::string toString(const Hashtable& h) + { + Array keys; + Array values; + h.arrayify(keys, values); + + std::string rtn = "["; + for (int i=0; i inline + const Value& Hashtable::get(const Key& key) const + { + TEST_FOR_EXCEPTION(!containsKey(key), + std::runtime_error, + "Hashtable::get: key " + << Teuchos::toString(key) + << " not found in Hashtable" + << toString()); + + const Array >& candidates + = data_[hashCode(key) % capacity_]; + + accumulateAvgFill(candidates.length()); + + for (int i=0; i& c = candidates[i]; + if (c.key_ == key) + { + return c.value_; + } + } + return mostRecentValue_; + } + + + template inline + void Hashtable::remove(const Key& key) + { + TEST_FOR_EXCEPTION(!containsKey(key), + std::runtime_error, + "Hashtable::remove: key " + << Teuchos::toString(key) + << " not found in Hashtable" + << toString()); + + count_--; + int h = hashCode(key) % capacity_; + const Array >& candidates = data_[h]; + + for (int i=0; i& c = candidates[i]; + if (c.key_ == key) + { + data_[h].remove(i); + break; + } + } + } + + template inline + void Hashtable::accumulateAvgFill(int n) const + { + avgDegeneracy_ = ((double) nHits_)/(nHits_ + 1.0) * avgDegeneracy_ + ((double) n)/(nHits_ + 1.0); + nHits_++; + } + + template inline + std::ostream& operator<<(std::ostream& os, const Hashtable& h) + { + return os << toString(h); + } + + +} + +#endif // TEUCHOS_HASHTABLE_H diff --git a/fastlib/trilinos/include/Teuchos_LAPACK.hpp b/fastlib/trilinos/include/Teuchos_LAPACK.hpp new file mode 100644 index 0000000000..ac1ad3d086 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_LAPACK.hpp @@ -0,0 +1,2219 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef _TEUCHOS_LAPACK_HPP_ +#define _TEUCHOS_LAPACK_HPP_ + +/*! \file Teuchos_LAPACK.hpp + \brief Templated interface class to LAPACK routines. +*/ +/** \example LAPACK/cxx_main.cpp + This is an example of how to use the Teuchos::LAPACK class. +*/ + +/* for INTEL_CXML, the second arg may need to be changed to 'one'. If so +the appropriate declaration of one will need to be added back into +functions that include the macro: +*/ +#if defined (INTEL_CXML) + unsigned int one=1; +#endif + +#ifdef CHAR_MACRO +#undef CHAR_MACRO +#endif +#if defined (INTEL_CXML) +#define CHAR_MACRO(char_var) &char_var, one +#else +#define CHAR_MACRO(char_var) &char_var +#endif + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_LAPACK_wrappers.hpp" + +/*! \class Teuchos::LAPACK + \brief The Templated LAPACK Wrapper Class. + + The Teuchos::LAPACK class is a wrapper that encapsulates LAPACK + (Linear Algebra Package). LAPACK provides portable, high- + performance implementations of linear, eigen, SVD, etc solvers. + + The standard LAPACK interface is Fortran-specific. Unfortunately, the + interface between C++ and Fortran is not standard across all computer + platforms. The Teuchos::LAPACK class provides C++ wrappers for the LAPACK + kernels in order to insulate the rest of Teuchos from the details of C++ to Fortran + translation. A Teuchos::LAPACK object is essentially nothing, but allows access to + the LAPACK wrapper functions. + + Teuchos::LAPACK is a serial interface only. This is appropriate since the standard + LAPACK are only specified for serial execution (or shared memory parallel). + + \note +
      +
    1. These templates are specialized to use the Fortran LAPACK routines for + scalar types \c float and \c double. + +
    2. If Teuchos is configured with \c --enable-teuchos-std::complex then these templates + are specialized for scalar types \c std::complex and \c std::complex also. + +
    3. A short description is given for each method. For more detailed documentation, see the + LAPACK website (\c http://www.netlib.org/lapack/ ). +
    +*/ + +namespace Teuchos +{ + + template + struct UndefinedLAPACKRoutine + { + // This function should not compile if there is an attempt to instantiate! + static inline T notDefined() { return T::LAPACK_routine_not_defined_for_this_type(); } + }; + + template + class LAPACK + { + public: + + typedef typename Teuchos::ScalarTraits::magnitudeType MagnitudeType; + + //! @name Constructors/Destructors. + //@{ + + //! Default Constructor. + inline LAPACK(void) {} + + //! Copy Constructor. + inline LAPACK(const LAPACK& lapack) {} + + //! Destructor. + inline virtual ~LAPACK(void) {} + //@} + + //! @name Symmetric Positive Definite Linear System Routines. + //@{ + + //! Computes the \c L*D*L' factorization of a Hermitian/symmetric positive definite tridiagonal matrix \c A. + void PTTRF(const OrdinalType n, ScalarType* d, ScalarType* e, OrdinalType* info) const; + + //! Solves a tridiagonal system \c A*X=B using the \L*D*L' factorization of \c A computed by PTTRF. + void PTTRS(const OrdinalType n, const OrdinalType nrhs, const ScalarType* d, const ScalarType* e, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //! Computes Cholesky factorization of a real symmetric positive definite matrix \c A. + void POTRF(const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* info) const; + + //! Solves a system of linear equations \c A*X=B, where \c A is a symmetric positive definite matrix factored by POTRF and the \c nrhs solutions are returned in \c B. + void POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //! Computes the inverse of a real symmetric positive definite matrix \c A using the Cholesky factorization \c A from POTRF. + void POTRI(const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* info) const; + + //! Estimates the reciprocal of the condition number (1-norm) of a real symmetric positive definite matrix \c A using the Cholesky factorization from POTRF. + + void POCON(const char UPLO, const OrdinalType n, const ScalarType* A, const OrdinalType lda, const ScalarType anorm, ScalarType* rcond, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + //! Computes the solution to a real system of linear equations \c A*X=B, where \c A is a symmetric positive definite matrix and the \c nrhs solutions are returned in \c B. + void POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //! Computes row and column scalings intended to equilibrate a symmetric positive definite matrix \c A and reduce its condition number (w.r.t. 2-norm). + void POEQU(const OrdinalType n, const ScalarType* A, const OrdinalType lda, ScalarType* S, ScalarType* scond, ScalarType* amax, OrdinalType* info) const; + + //! Improves the computed solution to a system of linear equations when the coefficient matrix is symmetric positive definite, and provides error bounds and backward error estimates for the solution. + void PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, const ScalarType* AF, const OrdinalType ldaf, const ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + //! Uses the Cholesky factorization to compute the solution to a real system of linear equations \c A*X=B, where \c A is symmetric positive definite. System can be equilibrated by POEQU and iteratively refined by PORFS, if requested. + void POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* AF, const OrdinalType ldaf, char EQUED, ScalarType* S, ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* rcond, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const; + //@} + + //! @name General Linear System Routines. + //@{ + + //! Solves an over/underdetermined real \c m by \c n linear system \c A using QR or LQ factorization of A. + void GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + //! Computes a QR factorization of a general \c m by \c n matrix \c A. + void GEQRF( const OrdinalType m, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + //! Computes an LU factorization of a general \c m by \c n matrix \c A using partial pivoting with row interchanges. + void GETRF(const OrdinalType m, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const; + + //! Solves a system of linear equations \c A*X=B or \c A'*X=B with a general \c n by \c n matrix \c A using the LU factorization computed by GETRF. + void GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, const OrdinalType* IPIV, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //! Computes an LU factorization of a \c n by \c n matrix tridiagonal matrix \c A using partial pivoting with row interchanges. + void GTTRF(const OrdinalType n, ScalarType* dl, ScalarType* d, ScalarType* du, ScalarType* du2, OrdinalType* IPIV, OrdinalType* info) const; + + //! Solves a system of linear equations \c A*X=B or \c A'*X=B or \c A^H*X=B with a tridiagonal matrix \c A using the LU factorization computed by GTTRF. + void GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const ScalarType* dl, const ScalarType* d, const ScalarType* du, const ScalarType* du2, const OrdinalType* IPIV, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //! Computes the inverse of a matrix \c A using the LU factorization computed by GETRF. + void GETRI(const OrdinalType n, ScalarType* A, const OrdinalType lda, const OrdinalType* IPIV, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + //! Estimates the reciprocal of the condition number of a general real matrix \c A, in either the 1-norm or the infinity-norm, using the LU factorization computed by GETRF. + void GECON(const char NORM, const OrdinalType n, const ScalarType* A, const OrdinalType lda, const ScalarType anorm, ScalarType* rcond, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + //! Computes the solution to a real system of linear equations \c A*X=B, where \c A is factored through GETRF and the \c nrhs solutions are computed through GETRS. + void GESV(const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, OrdinalType* IPIV, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //! Computes row and column scalings intended to equilibrate an \c m by \c n matrix \c A and reduce its condition number. + void GEEQU(const OrdinalType m, const OrdinalType n, const ScalarType* A, const OrdinalType lda, ScalarType* R, ScalarType* C, ScalarType* rowcond, ScalarType* colcond, ScalarType* amax, OrdinalType* info) const; + + //! Improves the computed solution to a system of linear equations and provides error bounds and backward error estimates for the solution. Use after GETRF/GETRS. + void GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, const ScalarType* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + //! Uses the LU factorization to compute the solution to a real system of linear equations \c A*X=B, returning error bounds on the solution and a condition estimate. + void GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, ScalarType* R, ScalarType* C, ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* rcond, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + /*! \brief Reduces a real symmetric matrix \c A to tridiagonal form by orthogonal similarity transformations. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void SYTRD(const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* D, ScalarType* E, ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + //! Reduces a real general matrix \c A to upper Hessenberg form by orthogonal similarity transformations. + void GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, ScalarType* A, const OrdinalType lda, ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + //! Solves a triangular linear system of the form \c A*X=B or \c A**T*X=B, where \c A is a triangular matrix. + void TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const; + + //@} + + //! @name Symmetric Eigenproblem Routines + //@{ + /*! \brief Computes the eigenvalues and, optionally, eigenvectors of a symmetric \c n by \c n matrix \c A in packed storage. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void SPEV(const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* AP, ScalarType* W, ScalarType* Z, const OrdinalType ldz, ScalarType* WORK, OrdinalType* info) const; + + /*! \brief Computes all the eigenvalues and, optionally, eigenvectors of a symmetric \c n by \c n matrix A. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void SYEV(const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* W, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! \brief Computes all the eigenvalues and, optionally, eigenvectors of a symmetric \c n by \c n matrix pencil \c {A,B}, where \c A is symmetric and \c B is symmetric positive-definite. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void SYGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, ScalarType* W, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! \brief Computes all the eigenvalues and, optionally, eigenvectors of a Hermitian \c n by \c n matrix A. + \note This method will call SYEV when ScalarType is \c float or \c double. + */ + void HEEV(const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, MagnitudeType* W, ScalarType* WORK, const OrdinalType lwork, MagnitudeType* RWORK, OrdinalType* info) const; + + /*! \brief Computes all the eigenvalues and, optionally, eigenvectors of a generalized Hermitian-definite \c n by \c n matrix pencil \c {A,B}, where \c A is Hermitian and \c B is Hermitian positive-definite. + \note This method will call SYGV when ScalarType is \c float or \c double. + */ + void HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, MagnitudeType* W, ScalarType* WORK, const OrdinalType lwork, MagnitudeType *RWORK, OrdinalType* info) const; + + //! Computes the eigenvalues and, optionally, eigenvectors of a symmetric tridiagonal \c n by \c n matrix \c A using implicit QL/QR. The eigenvectors can only be computed if \c A was reduced to tridiagonal form by SYTRD. + void STEQR(const char COMPZ, const OrdinalType n, ScalarType* D, ScalarType* E, ScalarType* Z, const OrdinalType ldz, ScalarType* WORK, OrdinalType* info) const; + //@} + + //! @name Non-Hermitian Eigenproblem Routines + //@{ + //! Computes the eigenvalues of a real upper Hessenberg matrix \c H and, optionally, the matrices \c T and \c Z from the Schur decomposition, where T is an upper quasi-triangular matrix and Z contains the Schur vectors. + void HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, ScalarType* H, const OrdinalType ldh, ScalarType* WR, ScalarType* WI, ScalarType* Z, const OrdinalType ldz, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! Computes for an \c n by \c n nonsymmetric matrix \c A, the eigenvalues, the Schur form \c T, and, optionally, the matrix of Schur vectors \c Z. When \c ScalarType is \c float or \c double, the real Schur form is computed. + \note (This is the version used for \c float and \c double, where \c select requires two arguments to represent a std::complex eigenvalue.) + */ + void GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(ScalarType*, ScalarType*), const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* sdim, ScalarType* WR, ScalarType* WI, ScalarType* VS, const OrdinalType ldvs, ScalarType* WORK, const OrdinalType lwork, OrdinalType* BWORK, OrdinalType* info) const; + + /*! Computes for an \c n by \c n nonsymmetric matrix \c A, the eigenvalues, the Schur form \c T, and, optionally, the matrix of Schur vectors \c Z. When \c ScalarType is \c float or \c double, the real Schur form is computed. + \note (This is the version used for \c std::complex and \c std::complex, where \c select requires one arguments to represent a std::complex eigenvalue.) + */ + void GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(ScalarType*), const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* sdim, ScalarType* W, ScalarType* VS, const OrdinalType ldvs, ScalarType* WORK, const OrdinalType lwork, MagnitudeType* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + + /*! Computes for an \c n by \c n nonsymmetric matrix \c A, the eigenvalues, the Schur form \c T, and, optionally, the matrix of Schur vectors \c Z. When \c ScalarType is \c float or \c double, the real Schur form is computed. + \note (This is the version used for any \c ScalarType, when the user doesn't want to enable the sorting functionality.) + */ + void GEES(const char JOBVS, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* sdim, MagnitudeType* WR, MagnitudeType* WI, ScalarType* VS, const OrdinalType ldvs, ScalarType* WORK, const OrdinalType lwork, MagnitudeType* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + + //! Computes for an \c n by \c n real nonsymmetric matrix \c A, the eigenvalues and, optionally, the left and/or right eigenvectors. + void GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* WR, ScalarType* WI, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + //! Computes for a pair of \c n by \c n nonsymmetric matrices (\c A,\c B) the generalized eigenvalues, and optionally, the left and/or right generalized eigenvectors. + void GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, MagnitudeType* ALPHAR, MagnitudeType* ALPHAI, ScalarType* BETA, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, MagnitudeType* LSCALE, MagnitudeType* RSCALE, MagnitudeType* abnrm, MagnitudeType* bbnrm, MagnitudeType* RCONDE, MagnitudeType* RCONDV, ScalarType* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const; + //@} + + //! @name Orthogonal matrix routines + //@{ + /*! \brief Overwrites the general real matrix \c m by \c n matrix \c C with the product of \c C and \c Q, which is the product of \c k elementary reflectors, as returned by GEQRF. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void ORMQR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType k, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* C, const OrdinalType ldc, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! \brief Generates an \c m by \c n matrix Q with orthonormal columns which is defined as the first \n columns of a product of \c k elementary reflectors of order \c m, as returned by GEQRF. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void ORGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! \brief Generates an \c m by \c n matrix Q with orthonormal columns which is defined as the first \n columns of a product of \c k elementary reflectors of order \c m, as returned by GEQRF. + \note This method will call ORGQR when the ScalarType is \c float or \c double. + */ + void UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! \brief Generates a real orthogonal matrix \c Q which is the product of \c ihi-ilo elementary reflectors of order \c n, as returned by GEHRD. On return \c Q is stored in \c A. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void ORGHR(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + + /*! \brief Overwrites the general real \c m by \c n matrix \c C with the product of \c C and \c Q, which is a product of \c ihi-ilo elementary reflectors, as returned by GEHRD. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + void ORMHR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, const ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* C, const OrdinalType ldc, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const; + //@} + + //! @name Triangular Matrix Routines + //@{ + + /*! Computes some or all of the right and/or left eigenvectors of an upper triangular matrix \c T. If ScalarType is \c float or \c double, then the matrix is quasi-triangular and arugments \c RWORK is ignored. + \note (This is the version used for \c float and \c double, where \c select requires two arguments to represent a std::complex eigenvalue.) + */ + void TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(ScalarType*, ScalarType*), const OrdinalType n, const ScalarType* T, const OrdinalType ldt, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, ScalarType* WORK, OrdinalType* info) const; + + /*! Computes some or all of the right and/or left eigenvectors of an upper triangular matrix \c T. If ScalarType is \c float or \c double, then the matrix is quasi-triangular and arugments \c RWORK is ignored. + \note (This is the version used for \c std::complex and \c std::complex, where \c select requires one arguments to represent a std::complex eigenvalue.) + */ + void TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(ScalarType*), const OrdinalType n, const ScalarType* T, const OrdinalType ldt, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, ScalarType* WORK, MagnitudeType* RWORK, OrdinalType* info) const; + + /*! Computes some or all of the right and/or left eigenvectors of an upper triangular matrix \c T. If ScalarType is \c float or \c double, then the matrix is quasi-triangular and arugments \c RWORK is ignored. + \note (This is the version used for any \c ScalarType, when the user doesn't want to enable the selecting functionality, with HOWMNY='A'.) + */ + void TREVC(const char SIDE, const OrdinalType n, const ScalarType* T, const OrdinalType ldt, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, ScalarType* WORK, MagnitudeType* RWORK, OrdinalType* info) const; + + /*! Reorders the Schur factorization of a matrix \c T via unitary similarity transformations so that the diagonal element of \c T with row index \c ifst is moved to row \c ilst. If \c ScalarType is \c float or \c double, then \c T should be in real Schur form and the operation affects the diagonal block referenced by \c ifst. + \note This method will ignore the WORK std::vector when ScalarType is \c std::complex or \c std::complex. + */ + void TREXC(const char COMPQ, const OrdinalType n, ScalarType* T, const OrdinalType ldt, ScalarType* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, ScalarType* WORK, OrdinalType* info) const; + + //@} + + //! @name Rotation/Reflection generators + //@{ + + //! Generates a plane rotation that zeros out the second component of the input std::vector. + void LARTG( const ScalarType f, const ScalarType g, MagnitudeType* c, ScalarType* s, ScalarType* r ) const; + + //! Generates an elementary reflector of order \c n that zeros out the last \c n-1 components of the input std::vector. + void LARFG( const OrdinalType n, ScalarType* alpha, ScalarType* x, const OrdinalType incx, ScalarType* tau ) const; + + //@} + + //! @name Random number generators + //@{ + //! Returns a random number from a uniform or normal distribution. + ScalarType LARND( const OrdinalType idist, OrdinalType* seed ) const; + + //! Returns a std::vector of random numbers from a chosen distribution. + void LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, ScalarType* v ) const; + //@} + + //! @name Machine Characteristics Routines. + //@{ + /*! \brief Determines machine parameters for floating point characteristics. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + ScalarType LAMCH(const char CMACH) const; + + /*! \brief Chooses problem-dependent parameters for the local environment. + \note This method should give parameters for good, but not optimal, performance on many currently + available computers. + */ + OrdinalType ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1 = -1, const OrdinalType N2 = -1, const OrdinalType N3 = -1, const OrdinalType N4 = -1 ) const; + //@} + + //! @name Miscellaneous Utilities. + //@{ + /*! \brief Computes x^2 + y^2 safely, to avoid overflow. + \note This method is not defined when the ScalarType is \c std::complex or \c std::complex. + */ + ScalarType LAPY2(const ScalarType x, const ScalarType y) const; + //@} + }; + + // END GENERAL TEMPLATE DECLARATION // + + // BEGIN GENERAL TEMPLATE IMPLEMENTATION // + + + template + void LAPACK::PTTRF(const OrdinalType n, ScalarType* d, ScalarType* e, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::PTTRS(const OrdinalType n, const OrdinalType nrhs, const ScalarType* d, const ScalarType* e, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POTRF(const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POTRI(const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POCON(const char UPLO, const OrdinalType n, const ScalarType* A, const OrdinalType lda, const ScalarType anorm, ScalarType* rcond, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POEQU(const OrdinalType n, const ScalarType* A, const OrdinalType lda, ScalarType* S, ScalarType* scond, ScalarType* amax, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, const ScalarType* AF, const OrdinalType ldaf, const ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* AF, const OrdinalType ldaf, char EQUED, ScalarType* S, ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* rcond, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEQRF( const OrdinalType m, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GETRF(const OrdinalType m, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, const OrdinalType* IPIV, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GTTRF(const OrdinalType n, ScalarType* dl, ScalarType* d, ScalarType* du, ScalarType* du2, OrdinalType* IPIV, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const ScalarType* dl, const ScalarType* d, const ScalarType* du, const ScalarType* du2, const OrdinalType* IPIV, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GETRI(const OrdinalType n, ScalarType* A, const OrdinalType lda, const OrdinalType* IPIV, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GECON(const char NORM, const OrdinalType n, const ScalarType* A, const OrdinalType lda, const ScalarType anorm, ScalarType* rcond, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GESV(const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, OrdinalType* IPIV, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEEQU(const OrdinalType m, const OrdinalType n, const ScalarType* A, const OrdinalType lda, ScalarType* R, ScalarType* C, ScalarType* rowcond, ScalarType* colcond, ScalarType* amax, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, const ScalarType* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, ScalarType* A, const OrdinalType lda, ScalarType* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, ScalarType* R, ScalarType* C, ScalarType* B, const OrdinalType ldb, ScalarType* X, const OrdinalType ldx, ScalarType* rcond, ScalarType* FERR, ScalarType* BERR, ScalarType* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::SYTRD(const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* D, ScalarType* E, ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, ScalarType* A, const OrdinalType lda, ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::SPEV(const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* AP, ScalarType* W, ScalarType* Z, const OrdinalType ldz, ScalarType* WORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::SYEV(const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* W, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::SYGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, ScalarType* W, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::HEEV(const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, MagnitudeType* W, ScalarType* WORK, const OrdinalType lwork, MagnitudeType* RWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, MagnitudeType* W, ScalarType* WORK, const OrdinalType lwork, MagnitudeType* RWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::STEQR(const char COMPZ, const OrdinalType n, ScalarType* D, ScalarType* E, ScalarType* Z, const OrdinalType ldz, ScalarType* WORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, ScalarType* H, const OrdinalType ldh, ScalarType* WR, ScalarType* WI, ScalarType* Z, const OrdinalType ldz, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(ScalarType*, ScalarType*), const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* sdim, ScalarType* WR, ScalarType* WI, ScalarType* VS, const OrdinalType ldvs, ScalarType* WORK, const OrdinalType lwork, OrdinalType* BWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(ScalarType*), const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* sdim, ScalarType* W, ScalarType* VS, const OrdinalType ldvs, ScalarType* WORK, const OrdinalType lwork, MagnitudeType *RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEES(const char JOBVS, const OrdinalType n, ScalarType* A, const OrdinalType lda, OrdinalType* sdim, MagnitudeType* WR, MagnitudeType* WI, ScalarType* VS, const OrdinalType ldvs, ScalarType* WORK, const OrdinalType lwork, MagnitudeType *RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* WR, ScalarType* WI, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, ScalarType* A, const OrdinalType lda, ScalarType* B, const OrdinalType ldb, MagnitudeType* ALPHAR, MagnitudeType* ALPHAI, ScalarType* BETA, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, MagnitudeType* LSCALE, MagnitudeType* RSCALE, MagnitudeType* abnrm, MagnitudeType* bbnrm, MagnitudeType* RCONDE, MagnitudeType* RCONDV, ScalarType* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::ORMQR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType k, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* C, const OrdinalType ldc, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::ORGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::ORGHR(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::ORMHR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, const ScalarType* A, const OrdinalType lda, const ScalarType* TAU, ScalarType* C, const OrdinalType ldc, ScalarType* WORK, const OrdinalType lwork, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(ScalarType*, ScalarType*), const OrdinalType n, const ScalarType* T, const OrdinalType ldt, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, ScalarType* WORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(ScalarType*), const OrdinalType n, const ScalarType* T, const OrdinalType ldt, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, ScalarType* WORK, MagnitudeType* RWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::TREVC(const char SIDE, const OrdinalType n, const ScalarType* T, const OrdinalType ldt, ScalarType* VL, const OrdinalType ldvl, ScalarType* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, ScalarType* WORK, MagnitudeType* RWORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::TREXC(const char COMPQ, const OrdinalType n, ScalarType* T, const OrdinalType ldt, ScalarType* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, ScalarType* WORK, OrdinalType* info) const + { + UndefinedLAPACKRoutine::notDefined(); + } + + template + ScalarType LAPACK::LAMCH(const char CMACH) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + template + OrdinalType LAPACK::ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1, const OrdinalType N2, const OrdinalType N3, const OrdinalType N4 ) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + template + ScalarType LAPACK::LAPY2(const ScalarType x, const ScalarType y) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::LARTG( const ScalarType f, const ScalarType g, MagnitudeType* c, ScalarType* s, ScalarType* r ) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::LARFG( const OrdinalType n, ScalarType* alpha, ScalarType* x, const OrdinalType incx, ScalarType* tau ) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + template + ScalarType LAPACK::LARND( const OrdinalType idist, OrdinalType* seed ) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + template + void LAPACK::LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, ScalarType* v ) const + { + return UndefinedLAPACKRoutine::notDefined(); + } + + // END GENERAL TEMPLATE IMPLEMENTATION // + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + + // BEGIN FLOAT PARTIAL SPECIALIZATION DECLARATION // + +#ifdef HAVE_TEUCHOS_BLASFLOAT + + template + class LAPACK + { + public: + inline LAPACK(void) {} + inline LAPACK(const LAPACK& lapack) {} + inline virtual ~LAPACK(void) {} + + // Symmetric positive definite linear system routines + void POTRF(const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* info) const; + void POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb, OrdinalType* info) const; + void PTTRF(const OrdinalType n, float* d, float* e, OrdinalType* info) const; + void PTTRS(const OrdinalType n, const OrdinalType nrhs, const float* d, const float* e, float* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRI(const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* info) const; + void POCON(const char UPLO, const OrdinalType n, const float* A, const OrdinalType lda, const float anorm, float* rcond, float* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, OrdinalType* info) const; + void POEQU(const OrdinalType n, const float* A, const OrdinalType lda, float* S, float* scond, float* amax, OrdinalType* info) const; + void PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, const float* AF, const OrdinalType ldaf, const float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* AF, const OrdinalType ldaf, char EQUED, float* S, float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + // General Linear System Routines + void GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEQRF( const OrdinalType m, const OrdinalType n, float* A, const OrdinalType lda, float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GETRF(const OrdinalType m, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const; + void GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, const OrdinalType* IPIV, float* B, const OrdinalType ldb, OrdinalType* info) const; + void GTTRF(const OrdinalType n, float* dl, float* d, float* du, float* du2, OrdinalType* IPIV, OrdinalType* info) const; + void GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const float* dl, const float* d, const float* du, const float* du2, const OrdinalType* IPIV, float* B, const OrdinalType ldb, OrdinalType* info) const; + + + void GETRI(const OrdinalType n, float* A, const OrdinalType lda, const OrdinalType* IPIV, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GECON(const char NORM, const OrdinalType n, const float* A, const OrdinalType lda, const float anorm, float* rcond, float* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void GESV(const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, OrdinalType* IPIV, float* B, const OrdinalType ldb, OrdinalType* info) const; + void GEEQU(const OrdinalType m, const OrdinalType n, const float* A, const OrdinalType lda, float* R, float* C, float* rowcond, float* colcond, float* amax, OrdinalType* info) const; + void GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, const float* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, float* R, float* C, float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void SYTRD(const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* D, float* E, float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, float* A, const OrdinalType lda, float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb, OrdinalType* info) const; + + // Symmetric eigenvalue routines. + void SPEV(const char JOBZ, const char UPLO, const OrdinalType n, float* AP, float* W, float* Z, const OrdinalType ldz, float* WORK, OrdinalType* info) const; + void SYEV(const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* W, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void SYGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* W, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void HEEV(const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* W, float* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* info) const; + void HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* W, float* WORK, const OrdinalType lwork, float *RWORK, OrdinalType* info) const; + void STEQR(const char COMPZ, const OrdinalType n, float* D, float* E, float* Z, const OrdinalType ldz, float* WORK, OrdinalType* info) const; + + // Non-Hermitian eigenvalue routines. + void HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, float* H, const OrdinalType ldh, float* WR, float* WI, float* Z, const OrdinalType ldz, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(float*, float*), const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* sdim, float* WR, float* WI, float* VS, const OrdinalType ldvs, float* WORK, const OrdinalType lwork, OrdinalType* BWORK, OrdinalType* info) const; + void GEES(const char JOBVS, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* sdim, float* WR, float* WI, float* VS, const OrdinalType ldvs, float* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + void GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, float* A, const OrdinalType lda, float* WR, float* WI, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* ALPHAR, float* ALPHAI, float* BETA, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, float* LSCALE, float* RSCALE, float* abnrm, float* bbnrm, float* RCONDE, float* RCONDV, float* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const; + + // Orthogonal matrix routines. + void ORMQR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType k, float* A, const OrdinalType lda, const float* TAU, float* C, const OrdinalType ldc, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void ORGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, float* A, const OrdinalType lda, const float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, float* A, const OrdinalType lda, const float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void ORGHR(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, float* A, const OrdinalType lda, const float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + void ORMHR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, const float* A, const OrdinalType lda, const float* TAU, float* C, const OrdinalType ldc, float* WORK, const OrdinalType lwork, OrdinalType* info) const; + + // Triangular matrix routines. + void TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(float*, float*), const OrdinalType n, const float* T, const OrdinalType ldt, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, float* WORK, OrdinalType* info) const; + void TREVC(const char SIDE, const OrdinalType n, const float* T, const OrdinalType ldt, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, float* WORK, float *RWORK, OrdinalType* info) const; + void TREXC(const char COMPQ, const OrdinalType n, float* T, const OrdinalType ldt, float* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, float* WORK, OrdinalType* info) const; + + // Rotation/reflection generators + void LARTG( const float f, const float g, float* c, float* s, float* r ) const; + void LARFG( const OrdinalType n, float* alpha, float* x, const OrdinalType incx, float* tau ) const; + + // Random number generators + float LARND( const OrdinalType idist, OrdinalType* seed ) const; + void LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, float* v ) const; + + // Machine characteristics. + float LAMCH(const char CMACH) const; + OrdinalType ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1 = -1, const OrdinalType N2 = -1, const OrdinalType N3 = -1, const OrdinalType N4 = -1 ) const; + + // Miscellaneous routines. + float LAPY2(const float x, const float y) const; + + }; + + // END FLOAT PARTIAL SPECIALIZATION DECLARATION // + + // BEGIN FLOAT PARTIAL SPECIALIZATION IMPLEMENTATION // + + template + void LAPACK::PTTRF(const OrdinalType n, float* d, float* e, OrdinalType* info) const + { + SPTTRF_F77(&n,d,e,info); + } + + template + void LAPACK::PTTRS(const OrdinalType n, const OrdinalType nrhs, const float* d, const float* e, float* B, const OrdinalType ldb, OrdinalType* info) const + { + SPTTRS_F77(&n,&nrhs,d,e,B,&ldb,info); + } + + template + void LAPACK::POTRF(const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* info) const + { + SPOTRF_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK::POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb, OrdinalType* info) const + { + SPOTRS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK::POTRI(const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* info) const + { + SPOTRI_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK::POCON(const char UPLO, const OrdinalType n, const float* A, const OrdinalType lda, const float anorm, float* rcond, float* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + SPOCON_F77(CHAR_MACRO(UPLO), &n, A, &lda, &anorm, rcond, WORK, IWORK, info); + } + + template + void LAPACK::POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, OrdinalType* info) const + { + SPOSV_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK::POEQU(const OrdinalType n, const float* A, const OrdinalType lda, float* S, float* scond, float* amax, OrdinalType* info) const + { + SPOEQU_F77(&n, A, &lda, S, scond, amax, info); + } + + template + void LAPACK::PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, const float* AF, const OrdinalType ldaf, const float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + SPORFS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, B, &ldb, X, &ldx, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* AF, const OrdinalType ldaf, char EQUED, float* S, float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + SPOSVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, CHAR_MACRO(EQUED), S, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SGELS_F77(CHAR_MACRO(TRANS), &m, &n, &nrhs, A, &lda, B, &ldb, WORK, &lwork, info); + } + + template + void LAPACK::GEQRF( const OrdinalType m, const OrdinalType n, float* A, const OrdinalType lda, float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SGEQRF_F77(&m, &n, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::GETRF(const OrdinalType m, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const + { + SGETRF_F77(&m, &n, A, &lda, IPIV, info); + } + + template + void LAPACK::GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, const OrdinalType* IPIV, float* B, const OrdinalType ldb, OrdinalType* info) const + { + SGETRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK::GTTRF(const OrdinalType n, float* dl, float* d, float* du, float* du2, OrdinalType* IPIV, OrdinalType* info) const + { + SGTTRF_F77(&n, dl, d, du, du2, IPIV, info); + } + + template + void LAPACK::GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const float* dl, const float* d, const float* du, const float* du2, const OrdinalType* IPIV, float* B, const OrdinalType ldb, OrdinalType* info) const + { + SGTTRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, dl, d, du, du2, IPIV, B, &ldb, info); + } + + template + void LAPACK::GETRI(const OrdinalType n, float* A, const OrdinalType lda, const OrdinalType* IPIV, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SGETRI_F77(&n, A, &lda, IPIV, WORK, &lwork, info); + } + + template + void LAPACK::GECON(const char NORM, const OrdinalType n, const float* A, const OrdinalType lda, const float anorm, float* rcond, float* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + SGECON_F77(CHAR_MACRO(NORM), &n, A, &lda, &anorm, rcond, WORK, IWORK, info); + } + + template + void LAPACK::GESV(const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, OrdinalType* IPIV, float* B, const OrdinalType ldb, OrdinalType* info) const + { + SGESV_F77(&n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK::GEEQU(const OrdinalType m, const OrdinalType n, const float* A, const OrdinalType lda, float* R, float* C, float* rowcond, float* colcond, float* amax, OrdinalType* info) const + { + SGEEQU_F77(&m, &n, A, &lda, R, C, rowcond, colcond, amax, info); + } + + template + void LAPACK::GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, const float* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + SGERFS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, B, &ldb, X, &ldx, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, float* A, const OrdinalType lda, float* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, float* R, float* C, float* B, const OrdinalType ldb, float* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, float* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + SGESVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, CHAR_MACRO(EQUED), R, C, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::SYTRD(const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* D, float* E, float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SSYTRD_F77(CHAR_MACRO(UPLO), &n, A, &lda, D, E, TAU, WORK, &lwork, info); + } + + template + void LAPACK::GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, float* A, const OrdinalType lda, float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SGEHRD_F77(&n, &ilo, &ihi, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const float* A, const OrdinalType lda, float* B, const OrdinalType ldb, OrdinalType* info) const + { + STRTRS_F77(CHAR_MACRO(UPLO), CHAR_MACRO(TRANS), CHAR_MACRO(DIAG), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK::SPEV(const char JOBZ, const char UPLO, const OrdinalType n, float* AP, float* W, float* Z, const OrdinalType ldz, float* WORK, OrdinalType* info) const + { + SSPEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, AP, W, Z, &ldz, WORK, info); + } + + template + void LAPACK::SYEV(const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* W, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SSYEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, W, WORK, &lwork, info); + } + + template + void LAPACK::SYGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* W, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SSYGV_F77(&itype, CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, B, &ldb, W, WORK, &lwork, info); + } + + template + void LAPACK::HEEV(const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* W, float* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* info) const + { + SSYEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, W, WORK, &lwork, info); + } + + template + void LAPACK::HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* W, float* WORK, const OrdinalType lwork, float *RWORK, OrdinalType* info) const + { + SSYGV_F77(&itype, CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, B, &ldb, W, WORK, &lwork, info); + } + + template + void LAPACK::STEQR(const char COMPZ, const OrdinalType n, float* D, float* E, float* Z, const OrdinalType ldz, float* WORK, OrdinalType* info) const + { + SSTEQR_F77(CHAR_MACRO(COMPZ), &n, D, E, Z, &ldz, WORK, info); + } + + template + void LAPACK::HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, float* H, const OrdinalType ldh, float* WR, float* WI, float* Z, const OrdinalType ldz, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SHSEQR_F77(CHAR_MACRO(JOB), CHAR_MACRO(COMPZ), &n, &ilo, &ihi, H, &ldh, WR, WI, Z, &ldz, WORK, &lwork, info); + } + + template + void LAPACK::GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(float*, float*), const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* sdim, float* WR, float* WI, float* VS, const OrdinalType ldvs, float* WORK, const OrdinalType lwork, OrdinalType* BWORK, OrdinalType* info) const + { + SGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(SORT), ptr2func, &n, A, &lda, sdim, WR, WI, VS, &ldvs, WORK, &lwork, BWORK, info); + } + + template + void LAPACK::GEES(const char JOBVS, const OrdinalType n, float* A, const OrdinalType lda, OrdinalType* sdim, float* WR, float* WI, float* VS, const OrdinalType ldvs, float* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(float*,float*) = NULL; + const char sort = 'N'; + SGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(sort), nullfptr, &n, A, &lda, sdim, WR, WI, VS, &ldvs, WORK, &lwork, BWORK, info); + } + + template + void LAPACK::GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, float* A, const OrdinalType lda, float* WR, float* WI, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SGEEV_F77(CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), &n, A, &lda, WR, WI, VL, &ldvl, VR, &ldvr, WORK, &lwork, info); + } + + template + void LAPACK::GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, float* A, const OrdinalType lda, float* B, const OrdinalType ldb, float* ALPHAR, float* ALPHAI, float* BETA, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, float* LSCALE, float* RSCALE, float* abnrm, float* bbnrm, float* RCONDE, float* RCONDV, float* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const + { + SGGEVX_F77(CHAR_MACRO(BALANC), CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), CHAR_MACRO(SENSE), &n, A, &lda, B, &ldb, ALPHAR, ALPHAI, BETA, VL, &ldvl, VR, &ldvr, ilo, ihi, LSCALE, RSCALE, abnrm, bbnrm, RCONDE, RCONDV, WORK, &lwork, IWORK, BWORK, info); + } + + template + void LAPACK::ORMQR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType k, float* A, const OrdinalType lda, const float* TAU, float* C, const OrdinalType ldc, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SORMQR_F77(CHAR_MACRO(SIDE), CHAR_MACRO(TRANS), &m, &n, &k, A, &lda, TAU, C, &ldc, WORK, &lwork, info); + } + + template + void LAPACK::ORGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, float* A, const OrdinalType lda, const float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SORGQR_F77( &m, &n, &k, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, float* A, const OrdinalType lda, const float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SORGQR_F77( &m, &n, &k, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::ORGHR(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, float* A, const OrdinalType lda, const float* TAU, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SORGHR_F77(&n, &ilo, &ihi, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::ORMHR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, const float* A, const OrdinalType lda, const float* TAU, float* C, const OrdinalType ldc, float* WORK, const OrdinalType lwork, OrdinalType* info) const + { + SORMHR_F77(CHAR_MACRO(SIDE), CHAR_MACRO(TRANS), &m, &n, &ilo, &ihi, A, &lda, TAU, C, &ldc, WORK, &lwork, info); + } + + template + void LAPACK::TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(float*,float*), const OrdinalType n, const float* T, const OrdinalType ldt, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, float* WORK, OrdinalType* info) const + { + STREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(HOWMNY), ptr2func, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, info); + } + + template + void LAPACK::TREVC(const char SIDE, const OrdinalType n, const float* T, const OrdinalType ldt, float* VL, const OrdinalType ldvl, float* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, float* WORK, float* RWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(float*,float*) = NULL; + const char whch = 'A'; + STREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(whch), nullfptr, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, info); + } + + template + void LAPACK::TREXC(const char COMPQ, const OrdinalType n, float* T, const OrdinalType ldt, float* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, float* WORK, OrdinalType* info) const + { + STREXC_F77(CHAR_MACRO(COMPQ), &n, T, &ldt, Q, &ldq, &ifst, &ilst, WORK, info); + } + + template + void LAPACK::LARTG( const float f, const float g, float* c, float* s, float* r ) const + { + SLARTG_F77(&f, &g, c, s, r); + } + + template + void LAPACK::LARFG( const OrdinalType n, float* alpha, float* x, const OrdinalType incx, float* tau ) const + { + SLARFG_F77(&n, alpha, x, &incx, tau); + } + + template + float LAPACK::LARND( const OrdinalType idist, OrdinalType* seed ) const + { + return(SLARND_F77(&idist, seed)); + } + + template + void LAPACK::LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, float* v ) const + { + SLARNV_F77(&idist, seed, &n, v); + } + + template + float LAPACK::LAMCH(const char CMACH) const + { + return(SLAMCH_F77(CHAR_MACRO(CMACH))); + } + + template + OrdinalType LAPACK::ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1, const OrdinalType N2, const OrdinalType N3, const OrdinalType N4 ) const + { + unsigned int opts_length = OPTS.length(); + // if user queries a Hermitian routine, change it to a symmetric routine + std::string temp_NAME = "s" + NAME; + if (temp_NAME.substr(1,2) == "he") { + temp_NAME.replace(1,2,"sy"); + } + unsigned int name_length = temp_NAME.length(); +#if defined (INTEL_CXML) + return ILAENV_F77(&ispec, &temp_NAME[0], name_length, &OPTS[0], opts_length, &N1, &N2, &N3, &N4 ); +#else + return ILAENV_F77(&ispec, &temp_NAME[0], &OPTS[0], &N1, &N2, &N3, &N4, name_length, opts_length ); +#endif + } + + template + float LAPACK::LAPY2(const float x, const float y) const + { + return SLAPY2_F77(&x, &y); + } + + // END FLOAT PARTIAL SPECIALIZATION IMPLEMENTATION // + +#endif // HAVE_TEUCHOS_BLASFLOAT + + // BEGIN DOUBLE PARTIAL SPECIALIZATION DECLARATION // + + template + class LAPACK + { + public: + inline LAPACK(void) {} + inline LAPACK(const LAPACK& lapack) {} + inline virtual ~LAPACK(void) {} + + // Symmetric positive definite linear system routines + void PTTRF(const OrdinalType n, double* d, double* e, OrdinalType* info) const; + void PTTRS(const OrdinalType n, const OrdinalType nrhs, const double* d, const double* e, double* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRF(const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* info) const; + void POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRI(const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* info) const; + void POCON(const char UPLO, const OrdinalType n, const double* A, const OrdinalType lda, const double anorm, double* rcond, double* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, OrdinalType* info) const; + void POEQU(const OrdinalType n, const double* A, const OrdinalType lda, double* S, double* scond, double* amax, OrdinalType* info) const; + void PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, const double* AF, const OrdinalType ldaf, const double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* AF, const OrdinalType ldaf, char EQUED, double* S, double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const; + + // General linear system routines + void GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEQRF( const OrdinalType m, const OrdinalType n, double* A, const OrdinalType lda, double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GETRF(const OrdinalType m, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const; + void GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, const OrdinalType* IPIV, double* B, const OrdinalType ldb, OrdinalType* info) const; + void GTTRF(const OrdinalType n, double* dl, double* d, double* du, double* du2, OrdinalType* IPIV, OrdinalType* info) const; + void GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const double* dl, const double* d, const double* du, const double* du2, const OrdinalType* IPIV, double* B, const OrdinalType ldb, OrdinalType* info) const; + void GETRI(const OrdinalType n, double* A, const OrdinalType lda, const OrdinalType* IPIV, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GECON(const char NORM, const OrdinalType n, const double* A, const OrdinalType lda, const double anorm, double* rcond, double* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void GESV(const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, OrdinalType* IPIV, double* B, const OrdinalType ldb, OrdinalType* info) const; + void GEEQU(const OrdinalType m, const OrdinalType n, const double* A, const OrdinalType lda, double* R, double* C, double* rowcond, double* colcond, double* amax, OrdinalType* info) const; + void GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, const double* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, double* R, double* C, double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const; + void SYTRD(const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* D, double* E, double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, double* A, const OrdinalType lda, double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb, OrdinalType* info) const; + + // Symmetric eigenproblem routines. + void SPEV(const char JOBZ, const char UPLO, const OrdinalType n, double* AP, double* W, double* Z, const OrdinalType ldz, double* WORK, OrdinalType* info) const; + void SYEV(const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* W, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void SYGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* W, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void HEEV(const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* W, double* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* info) const; + void HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* W, double* WORK, const OrdinalType lwork, double *RWORK, OrdinalType* info) const; + void STEQR(const char COMPZ, const OrdinalType n, double* D, double* E, double* Z, const OrdinalType ldz, double* WORK, OrdinalType* info) const; + + // Non-Hermitian eigenproblem routines. + void HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, double* H, const OrdinalType ldh, double* WR, double* WI, double* Z, const OrdinalType ldz, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(double*, double*), const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* sdim, double* WR, double* WI, double* VS, const OrdinalType ldvs, double* WORK, const OrdinalType lwork, OrdinalType* BWORK, OrdinalType* info) const; + void GEES(const char JOBVS, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* sdim, double* WR, double* WI, double* VS, const OrdinalType ldvs, double* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + void GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, double* A, const OrdinalType lda, double* WR, double* WI, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* ALPHAR, double* ALPHAI, double* BETA, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, double* LSCALE, double* RSCALE, double* abnrm, double* bbnrm, double* RCONDE, double* RCONDV, double* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const; + + // Orthogonal matrix routines. + void ORMQR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType k, double* A, const OrdinalType lda, const double* TAU, double* C, const OrdinalType ldc, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void ORGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, double* A, const OrdinalType lda, const double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, double* A, const OrdinalType lda, const double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void ORGHR(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, double* A, const OrdinalType lda, const double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + void ORMHR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, const double* A, const OrdinalType lda, const double* TAU, double* C, const OrdinalType ldc, double* WORK, const OrdinalType lwork, OrdinalType* info) const; + + // Triangular matrix routines. + void TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(double*,double*), const OrdinalType n, const double* T, const OrdinalType ldt, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, double* WORK, OrdinalType* info) const; + void TREVC(const char SIDE, const OrdinalType n, const double* T, const OrdinalType ldt, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, double* WORK, double* RWORK, OrdinalType* info) const; + void TREXC(const char COMPQ, const OrdinalType n, double* T, const OrdinalType ldt, double* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, double* WORK, OrdinalType* info) const; + + // Rotation/reflection generators + void LARTG( const double f, const double g, double* c, double* s, double* r ) const; + void LARFG( const OrdinalType n, double* alpha, double* x, const OrdinalType incx, double* tau ) const; + + // Random number generators + double LARND( const OrdinalType idist, OrdinalType* seed ) const; + void LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, double* v ) const; + + // Machine characteristic routines. + double LAMCH(const char CMACH) const; + OrdinalType ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1 = -1, const OrdinalType N2 = -1, const OrdinalType N3 = -1, const OrdinalType N4 = -1 ) const; + + // Miscellaneous routines. + double LAPY2(const double x, const double y) const; + + }; + + // END DOUBLE PARTIAL SPECIALIZATION DECLARATION // + + // BEGIN DOUBLE PARTIAL SPECIALIZATION IMPLEMENTATION // + + + template + void LAPACK::PTTRF(const OrdinalType n, double* d, double* e, OrdinalType* info) const + { + DPTTRF_F77(&n,d,e,info); + } + + template + void LAPACK::PTTRS(const OrdinalType n, const OrdinalType nrhs, const double* d, const double* e, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DPTTRS_F77(&n,&nrhs,d,e,B,&ldb,info); + } + + template + void LAPACK::POTRF(const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* info) const + { + DPOTRF_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK::POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DPOTRS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK::POTRI(const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* info) const + { + DPOTRI_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK::POCON(const char UPLO, const OrdinalType n, const double* A, const OrdinalType lda, const double anorm, double* rcond, double* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + DPOCON_F77(CHAR_MACRO(UPLO), &n, A, &lda, &anorm, rcond, WORK, IWORK, info); + } + + template + void LAPACK::POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DPOSV_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK::POEQU(const OrdinalType n, const double* A, const OrdinalType lda, double* S, double* scond, double* amax, OrdinalType* info) const + { + DPOEQU_F77(&n, A, &lda, S, scond, amax, info); + } + + template + void LAPACK::PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, const double* AF, const OrdinalType ldaf, const double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + DPORFS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, B, &ldb, X, &ldx, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* AF, const OrdinalType ldaf, char EQUED, double* S, double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + DPOSVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, CHAR_MACRO(EQUED), S, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DGELS_F77(CHAR_MACRO(TRANS), &m, &n, &nrhs, A, &lda, B, &ldb, WORK, &lwork, &info); + } + + template + void LAPACK::GEQRF( const OrdinalType m, const OrdinalType n, double* A, const OrdinalType lda, double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DGEQRF_F77(&m, &n, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::GETRF(const OrdinalType m, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const + { + DGETRF_F77(&m, &n, A, &lda, IPIV, info); + } + + template + void LAPACK::GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, const OrdinalType* IPIV, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DGETRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK::GTTRF(const OrdinalType n, double* dl, double* d, double* du, double* du2, OrdinalType* IPIV, OrdinalType* info) const + { + DGTTRF_F77(&n, dl, d, du, du2, IPIV, info); + } + + template + void LAPACK::GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const double* dl, const double* d, const double* du, const double* du2, const OrdinalType* IPIV, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DGTTRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, dl, d, du, du2, IPIV, B, &ldb, info); + } + + template + void LAPACK::GETRI(const OrdinalType n, double* A, const OrdinalType lda, const OrdinalType* IPIV, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DGETRI_F77(&n, A, &lda, IPIV, WORK, &lwork, info); + } + + template + void LAPACK::GECON(const char NORM, const OrdinalType n, const double* A, const OrdinalType lda, const double anorm, double* rcond, double* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + DGECON_F77(CHAR_MACRO(NORM), &n, A, &lda, &anorm, rcond, WORK, IWORK, info); + } + + template + void LAPACK::GESV(const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, OrdinalType* IPIV, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DGESV_F77(&n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK::GEEQU(const OrdinalType m, const OrdinalType n, const double* A, const OrdinalType lda, double* R, double* C, double* rowcond, double* colcond, double* amax, OrdinalType* info) const + { + DGEEQU_F77(&m, &n, A, &lda, R, C, rowcond, colcond, amax, info); + } + + template + void LAPACK::GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, const double* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + DGERFS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, B, &ldb, X, &ldx, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, double* A, const OrdinalType lda, double* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, double* R, double* C, double* B, const OrdinalType ldb, double* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, double* WORK, OrdinalType* IWORK, OrdinalType* info) const + { + DGESVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, CHAR_MACRO(EQUED), R, C, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, IWORK, info); + } + + template + void LAPACK::SYTRD(const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* D, double* E, double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DSYTRD_F77(CHAR_MACRO(UPLO), &n, A, &lda, D, E, TAU, WORK, &lwork, info); + } + + template + void LAPACK::GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, double* A, const OrdinalType lda, double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DGEHRD_F77(&n, &ilo, &ihi, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const double* A, const OrdinalType lda, double* B, const OrdinalType ldb, OrdinalType* info) const + { + DTRTRS_F77(CHAR_MACRO(UPLO), CHAR_MACRO(TRANS), CHAR_MACRO(DIAG), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK::SPEV(const char JOBZ, const char UPLO, const OrdinalType n, double* AP, double* W, double* Z, const OrdinalType ldz, double* WORK, OrdinalType* info) const + { + DSPEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, AP, W, Z, &ldz, WORK, info); + } + + template + void LAPACK::SYEV(const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* W, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DSYEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, W, WORK, &lwork, info); + } + + template + void LAPACK::SYGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* W, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DSYGV_F77(&itype, CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, B, &ldb, W, WORK, &lwork, info); + } + + template + void LAPACK::HEEV(const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* W, double* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* info) const + { + DSYEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, W, WORK, &lwork, info); + } + + template + void LAPACK::HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* W, double* WORK, const OrdinalType lwork, double *RWORK, OrdinalType* info) const + { + DSYGV_F77(&itype, CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, B, &ldb, W, WORK, &lwork, info); + } + + template + void LAPACK::STEQR(const char COMPZ, const OrdinalType n, double* D, double* E, double* Z, const OrdinalType ldz, double* WORK, OrdinalType* info) const + { + DSTEQR_F77(CHAR_MACRO(COMPZ), &n, D, E, Z, &ldz, WORK, info); + } + + template + void LAPACK::HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, double* H, const OrdinalType ldh, double* WR, double* WI, double* Z, const OrdinalType ldz, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DHSEQR_F77(CHAR_MACRO(JOB), CHAR_MACRO(COMPZ), &n, &ilo, &ihi, H, &ldh, WR, WI, Z, &ldz, WORK, &lwork, info); + } + + template + void LAPACK::GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(double*, double*), const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* sdim, double* WR, double* WI, double* VS, const OrdinalType ldvs, double* WORK, const OrdinalType lwork, OrdinalType* BWORK, OrdinalType* info) const + { + DGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(SORT), ptr2func, &n, A, &lda, sdim, WR, WI, VS, &ldvs, WORK, &lwork, BWORK, info); + } + + template + void LAPACK::GEES(const char JOBVS, const OrdinalType n, double* A, const OrdinalType lda, OrdinalType* sdim, double* WR, double* WI, double* VS, const OrdinalType ldvs, double* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(double*,double*) = NULL; + const char sort = 'N'; + DGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(sort), nullfptr, &n, A, &lda, sdim, WR, WI, VS, &ldvs, WORK, &lwork, BWORK, info); + } + + template + void LAPACK::GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, double* A, const OrdinalType lda, double* WR, double* WI, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DGEEV_F77(CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), &n, A, &lda, WR, WI, VL, &ldvl, VR, &ldvr, WORK, &lwork, info); + } + + template + void LAPACK::GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, double* A, const OrdinalType lda, double* B, const OrdinalType ldb, double* ALPHAR, double* ALPHAI, double* BETA, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, double* LSCALE, double* RSCALE, double* abnrm, double* bbnrm, double* RCONDE, double* RCONDV, double* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const + { + DGGEVX_F77(CHAR_MACRO(BALANC), CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), CHAR_MACRO(SENSE), &n, A, &lda, B, &ldb, ALPHAR, ALPHAI, BETA, VL, &ldvl, VR, &ldvr, ilo, ihi, LSCALE, RSCALE, abnrm, bbnrm, RCONDE, RCONDV, WORK, &lwork, IWORK, BWORK, info); + } + + template + void LAPACK::ORMQR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType k, double* A, const OrdinalType lda, const double* TAU, double* C, const OrdinalType ldc, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DORMQR_F77(CHAR_MACRO(SIDE), CHAR_MACRO(TRANS), &m, &n, &k, A, &lda, TAU, C, &ldc, WORK, &lwork, info); + } + + template + void LAPACK::ORGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, double* A, const OrdinalType lda, const double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DORGQR_F77( &m, &n, &k, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, double* A, const OrdinalType lda, const double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DORGQR_F77( &m, &n, &k, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::ORGHR(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, double* A, const OrdinalType lda, const double* TAU, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DORGHR_F77(&n, &ilo, &ihi, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK::ORMHR(const char SIDE, const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, const double* A, const OrdinalType lda, const double* TAU, double* C, const OrdinalType ldc, double* WORK, const OrdinalType lwork, OrdinalType* info) const + { + DORMHR_F77(CHAR_MACRO(SIDE), CHAR_MACRO(TRANS), &m, &n, &ilo, &ihi, A, &lda, TAU, C, &ldc, WORK, &lwork, info); + } + + template + void LAPACK::TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(double*,double*), const OrdinalType n, const double* T, const OrdinalType ldt, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, double* WORK, OrdinalType* info) const + { + DTREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(HOWMNY), ptr2func, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, info); + } + + template + void LAPACK::TREVC(const char SIDE, const OrdinalType n, const double* T, const OrdinalType ldt, double* VL, const OrdinalType ldvl, double* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, double* WORK, double* RWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(double*,double*) = NULL; + const char whch = 'A'; + DTREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(whch), nullfptr, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, info); + } + + template + void LAPACK::TREXC(const char COMPQ, const OrdinalType n, double* T, const OrdinalType ldt, double* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, double* WORK, OrdinalType* info) const + { + DTREXC_F77(CHAR_MACRO(COMPQ), &n, T, &ldt, Q, &ldq, &ifst, &ilst, WORK, info); + } + + template + void LAPACK::LARTG( const double f, const double g, double* c, double* s, double* r ) const + { + DLARTG_F77(&f, &g, c, s, r); + } + + template + void LAPACK::LARFG( const OrdinalType n, double* alpha, double* x, const OrdinalType incx, double* tau ) const + { + DLARFG_F77(&n, alpha, x, &incx, tau); + } + + template + double LAPACK::LARND( const OrdinalType idist, OrdinalType* seed ) const + { + return(DLARND_F77(&idist, seed)); + } + + template + void LAPACK::LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, double* v ) const + { + DLARNV_F77(&idist, seed, &n, v); + } + + template + double LAPACK::LAMCH(const char CMACH) const + { + return(DLAMCH_F77(CHAR_MACRO(CMACH))); + } + + template + OrdinalType LAPACK::ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1, const OrdinalType N2, const OrdinalType N3, const OrdinalType N4 ) const + { + unsigned int opts_length = OPTS.length(); + // if user queries a Hermitian routine, change it to a symmetric routine + std::string temp_NAME = "d" + NAME; + if (temp_NAME.substr(1,2) == "he") { + temp_NAME.replace(1,2,"sy"); + } + unsigned int name_length = temp_NAME.length(); +#if defined(INTEL_CXML) + return ILAENV_F77(&ispec, &temp_NAME[0], name_length, &OPTS[0], opts_length, &N1, &N2, &N3, &N4 ); +#else +# if defined(__INTEL_COMPILER) && defined(_WIN32) + return 0; +# else + return ILAENV_F77(&ispec, &temp_NAME[0], &OPTS[0], &N1, &N2, &N3, &N4, name_length, opts_length ); +# endif +#endif + } + + template + double LAPACK::LAPY2(const double x, const double y) const + { + return DLAPY2_F77(&x, &y); + } + + // END DOUBLE PARTIAL SPECIALIZATION IMPLEMENTATION // + +#ifdef HAVE_TEUCHOS_COMPLEX + +#ifdef HAVE_TEUCHOS_BLASFLOAT + + // BEGIN COMPLEX PARTIAL SPECIALIZATION DECLARATION // + + template + class LAPACK > + { + public: + inline LAPACK(void) {} + inline LAPACK(const LAPACK >& lapack) {} + inline virtual ~LAPACK(void) {} + + // Symmetric positive definite linear system routines + void PTTRF(const OrdinalType n, std::complex* d, std::complex* e, OrdinalType* info) const; + void PTTRS(const OrdinalType n, const OrdinalType nrhs, const std::complex* d, const std::complex* e, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRF(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const; + void POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRI(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const; + void POCON(const char UPLO, const OrdinalType n, const std::complex* A, const OrdinalType lda, const float anorm, float* rcond, std::complex* WORK, float* rwork, OrdinalType* info) const; + void POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void POEQU(const OrdinalType n, const std::complex* A, const OrdinalType lda, float* S, float* scond, float* amax, OrdinalType* info) const; + void PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const; + void POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, char EQUED, float* S, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const; + + // General Linear System Routines + void GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEQRF( const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, std::complex* A, const OrdinalType lda, const std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GETRF(const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const; + void GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void GTTRF(const OrdinalType n, std::complex* dl, std::complex* d, std::complex* du, std::complex* du2, OrdinalType* IPIV, OrdinalType* info) const; + void GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* dl, const std::complex* d, const std::complex* du, const std::complex* du2, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void GETRI(const OrdinalType n, std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GECON(const char NORM, const OrdinalType n, const std::complex* A, const OrdinalType lda, const float anorm, float* rcond, std::complex* WORK, float* RWORK, OrdinalType* info) const; + void GESV(const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void GEEQU(const OrdinalType m, const OrdinalType n, const std::complex* A, const OrdinalType lda, float* R, float* C, float* rowcond, float* colcond, float* amax, OrdinalType* info) const; + void GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const; + void GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, float* R, float* C, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const; + void GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + + // Symmetric eigenvalue routines. + void STEQR(const char COMPZ, const OrdinalType n, float* D, float* E, std::complex* Z, const OrdinalType ldz, float* WORK, OrdinalType* info) const; + void HEEV(const char JOBZ, const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, float* W, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* info) const; + void HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, float* W, std::complex* WORK, const OrdinalType lwork, float *RWORK, OrdinalType* info) const; + + // Non-Hermitian eigenvalue routines. + void HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* H, const OrdinalType ldh, std::complex* W, std::complex* Z, const OrdinalType ldz, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, std::complex* W, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + void GEES(const char JOBVS, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, float* WR, float* WI, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + void GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* W, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* info) const; +// void GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, float* ALPHAR, float* ALPHAI, std::complex* BETA, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, float* LSCALE, float* RSCALE, float* abnrm, float* bbnrm, float* RCONDE, float* RCONDV, std::complex* work, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const; + + // Triangular matrix routines. + void TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, float* RWORK, OrdinalType* info) const; + void TREVC(const char SIDE, const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, float* RWORK, OrdinalType* info) const; + void TREXC(const char COMPQ, const OrdinalType n, std::complex* T, const OrdinalType ldt, std::complex* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, std::complex* WORK, OrdinalType* info) const; + + // Rotation/reflection generators + void LARTG( const std::complex f, const std::complex g, float* c, std::complex* s, std::complex* r ) const; + void LARFG( const OrdinalType n, std::complex* alpha, std::complex* x, const OrdinalType incx, std::complex* tau ) const; + + // Random number generators + std::complex LARND( const OrdinalType idist, OrdinalType* seed ) const; + void LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, std::complex* v ) const; + + // Machine characteristics + OrdinalType ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1 = -1, const OrdinalType N2 = -1, const OrdinalType N3 = -1, const OrdinalType N4 = -1 ) const; + + }; + + // END COMPLEX PARTIAL SPECIALIZATION DECLARATION // + + // BEGIN COMPLEX PARTIAL SPECIALIZATION IMPLEMENTATION // + + template + void LAPACK >::PTTRF(const OrdinalType n, std::complex* d, std::complex* e, OrdinalType* info) const + { + CPTTRF_F77(&n,d,e,info); + } + + template + void LAPACK >::PTTRS(const OrdinalType n, const OrdinalType nrhs, const std::complex* d, const std::complex* e, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + CPTTRS_F77(&n,&nrhs,d,e,B,&ldb,info); + } + + template + void LAPACK >::POTRF(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const + { + CPOTRF_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK >::POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + CPOTRS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK >::POTRI(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const + { + CPOTRI_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK >::POCON(const char UPLO, const OrdinalType n, const std::complex* A, const OrdinalType lda, const float anorm, float* rcond, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CPOCON_F77(CHAR_MACRO(UPLO), &n, A, &lda, &anorm, rcond, WORK, RWORK, info); + } + + template + void LAPACK >::POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + CPOSV_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK >::POEQU(const OrdinalType n, const std::complex* A, const OrdinalType lda, float* S, float* scond, float* amax, OrdinalType* info) const + { + CPOEQU_F77(&n, A, &lda, S, scond, amax, info); + } + + template + void LAPACK >::PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CPORFS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, B, &ldb, X, &ldx, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, char EQUED, float* S, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CPOSVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, CHAR_MACRO(EQUED), S, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + CGELS_F77(CHAR_MACRO(TRANS), &m, &n, &nrhs, A, &lda, B, &ldb, WORK, &lwork, info); + } + + template + void LAPACK >::GEQRF( const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + CGEQRF_F77(&m, &n, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK >::UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, std::complex* A, const OrdinalType lda, const std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + CUNGQR_F77( &m, &n, &k, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK >::GETRF(const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const + { + CGETRF_F77(&m, &n, A, &lda, IPIV, info); + } + + template + void LAPACK >::GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* B , const OrdinalType ldb, OrdinalType* info) const + { + CGETRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK >::GTTRF(const OrdinalType n, std::complex* dl, std::complex* d, std::complex* du, std::complex* du2, OrdinalType* IPIV, OrdinalType* info) const + { + CGTTRF_F77(&n, dl, d, du, du2, IPIV, info); + } + + template + void LAPACK >::GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* dl, const std::complex* d, const std::complex* du, const std::complex* du2, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + CGTTRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, dl, d, du, du2, IPIV, B, &ldb, info); + } + + template + void LAPACK >::GETRI(const OrdinalType n, std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + CGETRI_F77(&n, A, &lda, IPIV, WORK, &lwork, info); + } + + template + void LAPACK >::GECON(const char NORM, const OrdinalType n, const std::complex* A, const OrdinalType lda, const float anorm, float* rcond, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CGECON_F77(CHAR_MACRO(NORM), &n, A, &lda, &anorm, rcond, WORK, RWORK, info); + } + + template + void LAPACK >::GESV(const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + CGESV_F77(&n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK >::GEEQU(const OrdinalType m, const OrdinalType n, const std::complex* A, const OrdinalType lda, float* R, float* C, float* rowcond, float* colcond, float* amax, OrdinalType* info) const + { + CGEEQU_F77(&m, &n, A, &lda, R, C, rowcond, colcond, amax, info); + } + + template + void LAPACK >::GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CGERFS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, B, &ldb, X, &ldx, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, float* R, float* C, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, float* rcond, float* FERR, float* BERR, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CGESVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, CHAR_MACRO(EQUED), R, C, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + CGEHRD_F77(&n, &ilo, &ihi, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK >::TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + CTRTRS_F77(CHAR_MACRO(UPLO), CHAR_MACRO(TRANS), CHAR_MACRO(DIAG), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK >::STEQR(const char COMPZ, const OrdinalType n, float* D, float* E, std::complex* Z, const OrdinalType ldz, float* WORK, OrdinalType* info) const + { + CSTEQR_F77(CHAR_MACRO(COMPZ), &n, D, E, Z, &ldz, WORK, info); + } + + template + void LAPACK >::HEEV(const char JOBZ, const char UPLO, const OrdinalType n, std::complex * A, const OrdinalType lda, float * W, std::complex * WORK, const OrdinalType lwork, float* RWORK, OrdinalType* info) const + { + CHEEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, W, WORK, &lwork, RWORK, info); + } + + template + void LAPACK >::HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, std::complex * A, const OrdinalType lda, std::complex * B, const OrdinalType ldb, float * W, std::complex * WORK, const OrdinalType lwork, float *RWORK, OrdinalType* info) const + { + CHEGV_F77(&itype, CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, B, &ldb, W, WORK, &lwork, RWORK, info); + } + + template + void LAPACK >::HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* H, const OrdinalType ldh, std::complex* W, std::complex* Z, const OrdinalType ldz, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + CHSEQR_F77(CHAR_MACRO(JOB), CHAR_MACRO(COMPZ), &n, &ilo, &ihi, H, &ldh, W, Z, &ldz, WORK, &lwork, info); + } + + template + void LAPACK >::GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, std::complex* W, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + CGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(SORT), ptr2func, &n, A, &lda, sdim, W, VS, &ldvs, WORK, &lwork, RWORK, BWORK, info); + } + + template + void LAPACK >::GEES(const char JOBVS, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, float* WR, float* WI, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(std::complex*) = NULL; + std::vector< std::complex > W(n); + const char sort = 'N'; + CGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(sort), nullfptr, &n, A, &lda, sdim, &W[0], VS, &ldvs, WORK, &lwork, RWORK, BWORK, info); + for (int i=0; i + void LAPACK >::GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* W, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, std::complex* WORK, const OrdinalType lwork, float* RWORK, OrdinalType* info) const + { + CGEEV_F77(CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), &n, A, &lda, W, VL, &ldvl, VR, &ldvr, WORK, &lwork, RWORK, info); + } + +/* + template + void LAPACK >::GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, float* ALPHAR, float* ALPHAI, std::complex* BETA, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, float* LSCALE, float* RSCALE, float* abnrm, float* bbnrm, float* RCONDE, float* RCONDV, std::complex* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const + { + std::vector< std::complex > ALPHA(n); + CGGEVX_F77(CHAR_MACRO(BALANC), CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), CHAR_MACRO(SENSE), &n, A, &lda, B, &ldb, &ALPHA[0], BETA, VL, &ldvl, VR, &ldvr, ilo, ihi, LSCALE, RSCALE, abnrm, bbnrm, RCONDE, RCONDV, WORK, &lwork, IWORK, BWORK, info); + for (int i=0; i + void LAPACK >::TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + CTREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(HOWMNY), ptr2func, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, RWORK, info); + } + + template + void LAPACK >::TREVC(const char SIDE, const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, float* RWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(std::complex*) = NULL; + const char whch = 'A'; + CTREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(whch), nullfptr, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, RWORK, info); + } + + template + void LAPACK >::TREXC(const char COMPQ, const OrdinalType n, std::complex* T, const OrdinalType ldt, std::complex* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, std::complex* WORK, OrdinalType* info) const + { + CTREXC_F77(CHAR_MACRO(COMPQ), &n, T, &ldt, Q, &ldq, &ifst, &ilst, info); + } + + template + void LAPACK >::LARTG( const std::complex f, const std::complex g, float* c, std::complex* s, std::complex* r ) const + { + CLARTG_F77(&f, &g, c, s, r); + } + + template + void LAPACK >::LARFG( const OrdinalType n, std::complex* alpha, std::complex* x, const OrdinalType incx, std::complex* tau ) const + { + CLARFG_F77(&n, alpha, x, &incx, tau); + } + + template + std::complex LAPACK >::LARND( const OrdinalType idist, OrdinalType* seed ) const + { + return(CLARND_F77(&idist, seed)); + } + + template + void LAPACK >::LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, std::complex* v ) const + { + CLARNV_F77(&idist, seed, &n, v); + } + + template + OrdinalType LAPACK >::ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1, const OrdinalType N2, const OrdinalType N3, const OrdinalType N4 ) const + { + unsigned int opts_length = OPTS.length(); + std::string temp_NAME = "c" + NAME; + unsigned int name_length = temp_NAME.length(); +#if defined (INTEL_CXML) + return ILAENV_F77(&ispec, &temp_NAME[0], name_length, &OPTS[0], opts_length, &N1, &N2, &N3, &N4 ); +#else + return ILAENV_F77(&ispec, &temp_NAME[0], &OPTS[0], &N1, &N2, &N3, &N4, name_length, opts_length ); +#endif + } + + // END COMPLEX PARTIAL SPECIALIZATION IMPLEMENTATION // + +#endif // HAVE_TEUCHOS_BLASFLOAT + + // BEGIN COMPLEX PARTIAL SPECIALIZATION DECLARATION // + + template + class LAPACK > + { + public: + inline LAPACK(void) {} + inline LAPACK(const LAPACK >& lapack) {} + inline virtual ~LAPACK(void) {} + + // Symmetric positive definite linear system routines + void PTTRF(const OrdinalType n, std::complex* d, std::complex* e, OrdinalType* info) const; + void PTTRS(const OrdinalType n, const OrdinalType nrhs, const std::complex* d, const std::complex* e, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRF(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const; + void POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void POTRI(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const; + void POCON(const char UPLO, const OrdinalType n, const std::complex* A, const OrdinalType lda, const double anorm, double* rcond, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void POEQU(const OrdinalType n, const std::complex* A, const OrdinalType lda, double* S, double* scond, double* amax, OrdinalType* info) const; + void PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, char EQUED, double* S, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const; + + // General Linear System Routines + void GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEQRF( const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, std::complex* A, const OrdinalType lda, const std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GETRF(const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const; + void GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void GTTRF(const OrdinalType n, std::complex* dl, std::complex* d, std::complex* du, std::complex* du2, OrdinalType* IPIV, OrdinalType* info) const; + void GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* dl, const std::complex* d, const std::complex* du, const std::complex* du2, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void GETRI(const OrdinalType n, std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GECON(const char NORM, const OrdinalType n, const std::complex* A, const OrdinalType lda, const double anorm, double* rcond, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void GESV(const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + void GEEQU(const OrdinalType m, const OrdinalType n, const std::complex* A, const OrdinalType lda, double* R, double* C, double* rowcond, double* colcond, double* amax, OrdinalType* info) const; + void GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, double* R, double* C, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const; + + // Symmetric eigenvalue routines. + void STEQR(const char COMPZ, const OrdinalType n, double* D, double* E, std::complex* Z, const OrdinalType ldz, double* WORK, OrdinalType* info) const; + void HEEV(const char JOBZ, const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, double* W, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* info) const; + void HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, double* W, std::complex* WORK, const OrdinalType lwork, double *RWORK, OrdinalType* info) const; + + // Non-hermitian eigenvalue routines. + void HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* H, const OrdinalType ldh, std::complex* W, std::complex* Z, const OrdinalType ldz, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const; + void GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, std::complex* W, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + void GEES(const char JOBVS, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, double* WR, double* WI, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* BWORK, OrdinalType* info) const; + void GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* W, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* info) const; +// void GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, double* ALPHAR, double* ALPHAI, std::complex* BETA, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, double* LSCALE, double* RSCALE, double* abnrm, double* bbnrm, double* RCONDE, double* RCONDV, std::complex* work, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const; + + // Triangular matrix routines. + void TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void TREVC(const char SIDE, const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, double* RWORK, OrdinalType* info) const; + void TREXC(const char COMPQ, const OrdinalType n, std::complex* T, const OrdinalType ldt, std::complex* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, std::complex* WORK, OrdinalType* info) const; + + // Rotation/reflection generators + void LARTG( const std::complex f, const std::complex g, double* c, std::complex* s, std::complex* r ) const; + void LARFG( const OrdinalType n, std::complex* alpha, std::complex* x, const OrdinalType incx, std::complex* tau ) const; + + // Random number generators + std::complex LARND( const OrdinalType idist, OrdinalType* seed ) const; + void LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, std::complex* v ) const; + + // Machine characteristics + OrdinalType ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1 = -1, const OrdinalType N2 = -1, const OrdinalType N3 = -1, const OrdinalType N4 = -1 ) const; + + }; + + // END COMPLEX PARTIAL SPECIALIZATION DECLARATION // + + // BEGIN COMPLEX PARTIAL SPECIALIZATION IMPLEMENTATION // + + template + void LAPACK >::PTTRF(const OrdinalType n, std::complex* d, std::complex* e, OrdinalType* info) const + { + ZPTTRF_F77(&n,d,e,info); + } + + template + void LAPACK >::PTTRS(const OrdinalType n, const OrdinalType nrhs, const std::complex* d, const std::complex* e, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZPTTRS_F77(&n,&nrhs,d,e,B,&ldb,info); + } + + template + void LAPACK >::POTRF(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const + { + ZPOTRF_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK >::POTRS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZPOTRS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK >::POTRI(const char UPLO, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* info) const + { + ZPOTRI_F77(CHAR_MACRO(UPLO), &n, A, &lda, info); + } + + template + void LAPACK >::POCON(const char UPLO, const OrdinalType n, const std::complex* A, const OrdinalType lda, const double anorm, double* rcond, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZPOCON_F77(CHAR_MACRO(UPLO), &n, A, &lda, &anorm, rcond, WORK, RWORK, info); + } + + template + void LAPACK >::POSV(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZPOSV_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK >::POEQU(const OrdinalType n, const std::complex* A, const OrdinalType lda, double* S, double* scond, double* amax, OrdinalType* info) const + { + ZPOEQU_F77(&n, A, &lda, S, scond, amax, info); + } + + template + void LAPACK >::PORFS(const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZPORFS_F77(CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, B, &ldb, X, &ldx, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::POSVX(const char FACT, const char UPLO, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, char EQUED, double* S, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZPOSVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(UPLO), &n, &nrhs, A, &lda, AF, &ldaf, CHAR_MACRO(EQUED), S, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::GELS(const char TRANS, const OrdinalType m, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + ZGELS_F77(CHAR_MACRO(TRANS), &m, &n, &nrhs, A, &lda, B, &ldb, WORK, &lwork, info); + } + + template + void LAPACK >::GEQRF( const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + ZGEQRF_F77(&m, &n, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK >::UNGQR(const OrdinalType m, const OrdinalType n, const OrdinalType k, std::complex* A, const OrdinalType lda, const std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + ZUNGQR_F77( &m, &n, &k, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK >::GETRF(const OrdinalType m, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, OrdinalType* info) const + { + ZGETRF_F77(&m, &n, A, &lda, IPIV, info); + } + + template + void LAPACK >::GETRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZGETRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK >::GTTRF(const OrdinalType n, std::complex* dl, std::complex* d, std::complex* du, std::complex* du2, OrdinalType* IPIV, OrdinalType* info) const + { + ZGTTRF_F77(&n, dl, d, du, du2, IPIV, info); + } + + template + void LAPACK >::GTTRS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* dl, const std::complex* d, const std::complex* du, const std::complex* du2, const OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZGTTRS_F77(CHAR_MACRO(TRANS), &n, &nrhs, dl, d, du, du2, IPIV, B, &ldb, info); + } + + template + void LAPACK >::GETRI(const OrdinalType n, std::complex* A, const OrdinalType lda, const OrdinalType* IPIV, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + ZGETRI_F77(&n, A, &lda, IPIV, WORK, &lwork, info); + } + + template + void LAPACK >::GECON(const char NORM, const OrdinalType n, const std::complex* A, const OrdinalType lda, const double anorm, double* rcond, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZGECON_F77(CHAR_MACRO(NORM), &n, A, &lda, &anorm, rcond, WORK, RWORK, info); + } + + template + void LAPACK >::GESV(const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, OrdinalType* IPIV, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZGESV_F77(&n, &nrhs, A, &lda, IPIV, B, &ldb, info); + } + + template + void LAPACK >::GEEQU(const OrdinalType m, const OrdinalType n, const std::complex* A, const OrdinalType lda, double* R, double* C, double* rowcond, double* colcond, double* amax, OrdinalType* info) const + { + ZGEEQU_F77(&m, &n, A, &lda, R, C, rowcond, colcond, amax, info); + } + + template + void LAPACK >::GERFS(const char TRANS, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, const std::complex* AF, const OrdinalType ldaf, const OrdinalType* IPIV, const std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZGERFS_F77(CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, B, &ldb, X, &ldx, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::GESVX(const char FACT, const char TRANS, const OrdinalType n, const OrdinalType nrhs, std::complex* A, const OrdinalType lda, std::complex* AF, const OrdinalType ldaf, OrdinalType* IPIV, char EQUED, double* R, double* C, std::complex* B, const OrdinalType ldb, std::complex* X, const OrdinalType ldx, double* rcond, double* FERR, double* BERR, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZGESVX_F77(CHAR_MACRO(FACT), CHAR_MACRO(TRANS), &n, &nrhs, A, &lda, AF, &ldaf, IPIV, CHAR_MACRO(EQUED), R, C, B, &ldb, X, &ldx, rcond, FERR, BERR, WORK, RWORK, info); + } + + template + void LAPACK >::GEHRD(const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* A, const OrdinalType lda, std::complex* TAU, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + ZGEHRD_F77(&n, &ilo, &ihi, A, &lda, TAU, WORK, &lwork, info); + } + + template + void LAPACK >::TRTRS(const char UPLO, const char TRANS, const char DIAG, const OrdinalType n, const OrdinalType nrhs, const std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, OrdinalType* info) const + { + ZTRTRS_F77(CHAR_MACRO(UPLO), CHAR_MACRO(TRANS), CHAR_MACRO(DIAG), &n, &nrhs, A, &lda, B, &ldb, info); + } + + template + void LAPACK >::STEQR(const char COMPZ, const OrdinalType n, double* D, double* E, std::complex* Z, const OrdinalType ldz, double* WORK, OrdinalType* info) const + { + ZSTEQR_F77(CHAR_MACRO(COMPZ), &n, D, E, Z, &ldz, WORK, info); + } + + template + void LAPACK >::HEEV(const char JOBZ, const char UPLO, const OrdinalType n, std::complex * A, const OrdinalType lda, double * W, std::complex * WORK, const OrdinalType lwork, double* RWORK, OrdinalType* info) const + { + ZHEEV_F77(CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, W, WORK, &lwork, RWORK, info); + } + + template + void LAPACK >::HEGV(const OrdinalType itype, const char JOBZ, const char UPLO, const OrdinalType n, std::complex * A, const OrdinalType lda, std::complex * B, const OrdinalType ldb, double * W, std::complex * WORK, const OrdinalType lwork, double *RWORK, OrdinalType* info) const + { + ZHEGV_F77(&itype, CHAR_MACRO(JOBZ), CHAR_MACRO(UPLO), &n, A, &lda, B, &ldb, W, WORK, &lwork, RWORK, info); + } + + template + void LAPACK >::HSEQR(const char JOB, const char COMPZ, const OrdinalType n, const OrdinalType ilo, const OrdinalType ihi, std::complex* H, const OrdinalType ldh, std::complex* W, std::complex* Z, const OrdinalType ldz, std::complex* WORK, const OrdinalType lwork, OrdinalType* info) const + { + ZHSEQR_F77(CHAR_MACRO(JOB), CHAR_MACRO(COMPZ), &n, &ilo, &ihi, H, &ldh, W, Z, &ldz, WORK, &lwork, info); + } + + template + void LAPACK >::GEES(const char JOBVS, const char SORT, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, std::complex* W, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + ZGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(SORT), ptr2func, &n, A, &lda, sdim, W, VS, &ldvs, WORK, &lwork, RWORK, BWORK, info); + } + + template + void LAPACK >::GEES(const char JOBVS, const OrdinalType n, std::complex* A, const OrdinalType lda, OrdinalType* sdim, double* WR, double* WI, std::complex* VS, const OrdinalType ldvs, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* BWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(std::complex*) = NULL; + std::vector< std::complex > W(n); + const char sort = 'N'; + ZGEES_F77(CHAR_MACRO(JOBVS), CHAR_MACRO(sort), nullfptr, &n, A, &lda, sdim, &W[0], VS, &ldvs, WORK, &lwork, RWORK, BWORK, info); + for (int i=0; i + void LAPACK >::GEEV(const char JOBVL, const char JOBVR, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* W, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, std::complex* WORK, const OrdinalType lwork, double* RWORK, OrdinalType* info) const + { + ZGEEV_F77(CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), &n, A, &lda, W, VL, &ldvl, VR, &ldvr, WORK, &lwork, RWORK, info); + } + +/* + template + void LAPACK >::GGEVX(const char BALANC, const char JOBVL, const char JOBVR, const char SENSE, const OrdinalType n, std::complex* A, const OrdinalType lda, std::complex* B, const OrdinalType ldb, double* ALPHAR, double* ALPHAI, std::complex* BETA, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, OrdinalType* ilo, OrdinalType* ihi, double* LSCALE, double* RSCALE, double* abnrm, double* bbnrm, double* RCONDE, double* RCONDV, std::complex* WORK, const OrdinalType lwork, OrdinalType* IWORK, OrdinalType* BWORK, OrdinalType* info) const + { + std::vector< std::complex > ALPHA(n); + ZGGEVX_F77(CHAR_MACRO(BALANC), CHAR_MACRO(JOBVL), CHAR_MACRO(JOBVR), CHAR_MACRO(SENSE), &n, A, &lda, B, &ldb, &ALPHA[0], BETA, VL, &ldvl, VR, &ldvr, ilo, ihi, LSCALE, RSCALE, abnrm, bbnrm, RCONDE, RCONDV, WORK, &lwork, IWORK, BWORK, info); + for (int i=0; i + void LAPACK >::TREVC(const char SIDE, const char HOWMNY, OrdinalType (*ptr2func)(std::complex*), const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + ZTREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(HOWMNY), ptr2func, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, RWORK, info); + } + + template + void LAPACK >::TREVC(const char SIDE, const OrdinalType n, const std::complex* T, const OrdinalType ldt, std::complex* VL, const OrdinalType ldvl, std::complex* VR, const OrdinalType ldvr, const OrdinalType mm, OrdinalType* m, std::complex* WORK, double* RWORK, OrdinalType* info) const + { + OrdinalType (*nullfptr)(std::complex*) = NULL; + const char whch = 'A'; + ZTREVC_F77(CHAR_MACRO(SIDE), CHAR_MACRO(whch), nullfptr, &n, T, &ldt, VL, &ldvl, VR, &ldvr, &mm, m, WORK, RWORK, info); + } + + template + void LAPACK >::TREXC(const char COMPQ, const OrdinalType n, std::complex* T, const OrdinalType ldt, std::complex* Q, const OrdinalType ldq, OrdinalType ifst, OrdinalType ilst, std::complex* WORK, OrdinalType* info) const + { + ZTREXC_F77(CHAR_MACRO(COMPQ), &n, T, &ldt, Q, &ldq, &ifst, &ilst, info); + } + + template + void LAPACK >::LARTG( const std::complex f, const std::complex g, double* c, std::complex* s, std::complex* r ) const + { + ZLARTG_F77(&f, &g, c, s, r); + } + + template + void LAPACK >::LARFG( const OrdinalType n, std::complex* alpha, std::complex* x, const OrdinalType incx, std::complex* tau ) const + { + ZLARFG_F77(&n, alpha, x, &incx, tau); + } + + template + std::complex LAPACK >::LARND( const OrdinalType idist, OrdinalType* seed ) const + { + return(ZLARND_F77(&idist, seed)); + } + + template + void LAPACK >::LARNV( const OrdinalType idist, OrdinalType* seed, const OrdinalType n, std::complex* v ) const + { + ZLARNV_F77(&idist, seed, &n, v); + } + + template + OrdinalType LAPACK >::ILAENV( const OrdinalType ispec, const std::string& NAME, const std::string& OPTS, const OrdinalType N1, const OrdinalType N2, const OrdinalType N3, const OrdinalType N4 ) const + { + unsigned int opts_length = OPTS.length(); + std::string temp_NAME = "z" + NAME; + unsigned int name_length = temp_NAME.length(); +#if defined (INTEL_CXML) + return ILAENV_F77(&ispec, &temp_NAME[0], name_length, &OPTS[0], opts_length, &N1, &N2, &N3, &N4 ); +#else + return ILAENV_F77(&ispec, &temp_NAME[0], &OPTS[0], &N1, &N2, &N3, &N4, name_length, opts_length ); +#endif + } + + // END COMPLEX PARTIAL SPECIALIZATION IMPLEMENTATION // + +#endif // HAVE_TEUCHOS_COMPLEX + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} // namespace Teuchos + +#endif // _TEUCHOS_LAPACK_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_LAPACK_wrappers.hpp b/fastlib/trilinos/include/Teuchos_LAPACK_wrappers.hpp new file mode 100644 index 0000000000..33c312b437 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_LAPACK_wrappers.hpp @@ -0,0 +1,771 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef _TEUCHOS_LAPACK_WRAPPERS_HPP_ +#define _TEUCHOS_LAPACK_WRAPPERS_HPP_ + +#include "Teuchos_ConfigDefs.hpp" + +/*! \file Teuchos_LAPACK_wrappers.hpp + \brief The Templated LAPACK wrappers +*/ +/* Define fcd (Fortran Teuchos_fcd descriptor) for non-standard situations */ + +#if defined(CRAY_T3X) || defined(INTEL_CXML) || defined(INTEL_MKL) + +#if defined(CRAY_T3X) + +#include +#define PREFIX +#define Teuchos_fcd fcd + +#define DGEQRF_F77 F77_FUNC(sgeqrf,SGEQRF) +#define DGETRF_F77 F77_FUNC(sgetrf,SGETRF) +#define DGETRS_F77 F77_FUNC(sgetrs,SGETRS) +#define DGTTRF_F77 F77_FUNC(sgttrf,SGTTRF) +#define DGTTRS_F77 F77_FUNC(sgttrs,SGTTRS) +#define DPTTRF_F77 F77_FUNC(spttrf,SPTTRF) +#define DPTTRS_F77 F77_FUNC(spttrs,SPTTRS) +#define DGETRI_F77 F77_FUNC(sgetri,SGETRI) +#define DGERFS_F77 F77_FUNC(sgerfs,SGERFS) +#define DGECON_F77 F77_FUNC(sgecon,SGECON) +#define DGESVX_F77 F77_FUNC(sgesvx,SGESVX) +#define DGESV_F77 F77_FUNC(sgesv,SGESV) +#define DGEEQU_F77 F77_FUNC(sgeequ,SGEEQU) +#define DSYTRD_F77 F77_FUNC(ssytrd,SSYTRD) +#define DPOTRF_F77 F77_FUNC(spotrf,SPOTRF) +#define DPOTRS_F77 F77_FUNC(spotrs,SPOTRS) +#define DPOTRI_F77 F77_FUNC(spotri,SPOTRI) +#define DPOCON_F77 F77_FUNC(spocon,SPOCON) +#define DPOSV_F77 F77_FUNC(sposv,SPOSV) +#define DPOEQU_F77 F77_FUNC(spoequ,SPOEQU) +#define DPORFS_F77 F77_FUNC(sporfs,SPORFS) +#define DPOSVX_F77 F77_FUNC(sposvx,SPOSVX) +#define DLAMCH_F77 F77_FUNC(slamch,SLAMCH) +#define DTRTRS_F77 F77_FUNC(strtrs,STRTRS) +#define DGELS_F77 F77_FUNC(sgels,SGELS) +#define DGEEV_F77 F77_FUNC(sgeev,SGEEV) +#define DGGEVX_F77 F77_FUNC(sggevx,SGGEVX) +#define DGEHRD_F77 F77_FUNC(sgehrd,SGEHRD) +#define DHSEQR_F77 F77_FUNC(shseqr,SHSEQR) +#define DORMQR_F77 F77_FUNC(sormqr,SORMQR) +#define DORGQR_F77 F77_FUNC(sorgqr,SORGQR) +#define DORGHR_F77 F77_FUNC(sorghr,SORGHR) +#define DORMHR_F77 F77_FUNC(sormhr,SORMHR) +#define DTREVC_F77 F77_FUNC(strevc,STREVC) +#define DTREXC_F77 F77_FUNC(strexc,STREXC) +#define DGEES_F77 F77_FUNC(sgees,SGEES) +#define DSPEV_F77 F77_FUNC(sspev,SSPEV) +#define DSYEV_F77 F77_FUNC(ssyev,SSYEV) +#define DSYGV_F77 F77_FUNC(ssygv,SSYGV) +#define DSTEQR_F77 F77_FUNC(ssteqr,SSTEQR) +#define DLAPY2_F77 F77_FUNC(slapy2,SLAPY2) +#define DLARTG_F77 F77_FUNC(slartg,SLARTG) +#define DLARFG_F77 F77_FUNC(slarfg,SLARFG) +#define DLARND_F77 F77_FUNC(slarnd,SLARND) +#define DLARNV_F77 F77_FUNC(slarnv,SLARNV) +#define ILAENV_F77 F77_FUNC(ilaenv,ILAENV) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZGEQRF_F77 F77_FUNC(cgeqrf,CGEQRF) +#define ZUNGQR_F77 F77_FUNC(cungqr,CUNGQR) +#define ZGETRF_F77 F77_FUNC(cgetrf,CGETRF) +#define ZGETRS_F77 F77_FUNC(cgetrs,CGETRS) +#define ZGTTRF_F77 F77_FUNC(cgttrf,CGTTRF) +#define ZGTTRS_F77 F77_FUNC(cgttrs,CGTTRS) +#define ZPTTRF_F77 F77_FUNC(cpttrf,CPTTRF) +#define ZPTTRS_F77 F77_FUNC(cpttrs,CPTTRS) +#define ZGETRI_F77 F77_FUNC(cgetri,CGETRI) +#define ZGERFS_F77 F77_FUNC(cgerfs,CGERFS) +#define ZGECON_F77 F77_FUNC(cgecon,CGECON) +#define ZGESVX_F77 F77_FUNC(cgesvx,CGESVX) +#define ZGESV_F77 F77_FUNC(cgesv,CGESV) +#define ZGEEQU_F77 F77_FUNC(cgeequ,CGEEQU) +#define ZPOTRF_F77 F77_FUNC(cpotrf,CPOTRF) +#define ZPOTRS_F77 F77_FUNC(cpotrs,CPOTRS) +#define ZPOTRI_F77 F77_FUNC(cpotri,CPOTRI) +#define ZPOCON_F77 F77_FUNC(cpocon,CPOCON) +#define ZPOSV_F77 F77_FUNC(cposv,CPOSV) +#define ZPOEQU_F77 F77_FUNC(cpoequ,CPOEQU) +#define ZPORFS_F77 F77_FUNC(cporfs,CPORFS) +#define ZPOSVX_F77 F77_FUNC(cposvx,CPOSVX) +#define ZTRTRS_F77 F77_FUNC(ctrtrs,CTRTRS) +#define ZGELS_F77 F77_FUNC(cgels,CGELS) +#define ZGEEV_F77 F77_FUNC(cgeev,CGEEV) +//#define ZGGEVX_F77 F77_FUNC(cggevx,CGGEVX) +#define ZGEHRD_F77 F77_FUNC(cgehrd,CGEHRD) +#define ZHSEQR_F77 F77_FUNC(chseqr,CHSEQR) +#define ZTREVC_F77 F77_FUNC(ctrevc,CTREVC) +#define ZTREXC_F77 F77_FUNC(ctrexc,CTREXC) +#define ZGEES_F77 F77_FUNC(cgees,CGEES) +#define ZSTEQR_F77 F77_FUNC(csteqr,CSTEQR) +#define ZHEEV_F77 F77_FUNC(cheev,CHEEV) +#define ZHEGV_F77 F77_FUNC(chegv,CHEGV) +#define ZLARTG_F77 F77_FUNC(clartg,cLARTG) +#define ZLARFG_F77 F77_FUNC(clarfg,cLARFG) +#define ZLARND_F77 F77_FUNC(clarnd,CLARND) +#define ZLARNV_F77 F77_FUNC(clarnv,CLARNV) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#elif defined(INTEL_CXML) + +#define PREFIX __stdcall +#define Teuchos_fcd const char *, unsigned int + +#define DGEQRF_F77 F77_FUNC(dgeqrf,DGEQRF) +#define DGETRF_F77 F77_FUNC(dgetrf,DGETRF) +#define DGETRS_F77 F77_FUNC(dgetrs,DGETRS) +#define DGTTRF_F77 F77_FUNC(dgttrf,DGTTRF) +#define DGTTRS_F77 F77_FUNC(dgttrs,DGTTRS) +#define DPTTRF_F77 F77_FUNC(dpttrf,DPTTRF) +#define DPTTRS_F77 F77_FUNC(dpttrs,DPTTRS) +#define DGETRI_F77 F77_FUNC(dgetri,DGETRI) +#define DGERFS_F77 F77_FUNC(dgerfs,DGERFS) +#define DGECON_F77 F77_FUNC(dgecon,DGECON) +#define DGESVX_F77 F77_FUNC(dgesvx,DGESVX) +#define DGESV_F77 F77_FUNC(dgesv,DGESV) +#define DGEEQU_F77 F77_FUNC(dgeequ,DGEEQU) +#define DSYTRD_F77 F77_FUNC(dsytrd,DSYTRD) +#define DPOTRF_F77 F77_FUNC(dpotrf,DPOTRF) +#define DPOTRS_F77 F77_FUNC(dpotrs,DPOTRS) +#define DPOTRI_F77 F77_FUNC(dpotri,DPOTRI) +#define DPOCON_F77 F77_FUNC(dpocon,DPOCON) +#define DPOSV_F77 F77_FUNC(dposv,DPOSV) +#define DPOEQU_F77 F77_FUNC(dpoequ,DPOEQU) +#define DPORFS_F77 F77_FUNC(dporfs,DPORFS) +#define DPOSVX_F77 F77_FUNC(dposvx,DPOSVX) +#define DTRTRS_F77 F77_FUNC(dtrtrs,DTRTRS) +#define DLAMCH_F77 F77_FUNC(dlamch,DLAMCH) +#define DGELS_F77 F77_FUNC(dgels,DGELS) +#define DGEEV_F77 F77_FUNC(dgeev,DGEEV) +#define DGGEVX_F77 F77_FUNC(dggevx,DGGEVX) +#define DGEHRD_F77 F77_FUNC(dgehrd,DGEHRD) +#define DHSEQR_F77 F77_FUNC(dhseqr,DHSEQR) +#define DORGHR_F77 F77_FUNC(dorghr,DORGHR) +#define DORGQR_F77 F77_FUNC(dorgqr,DORGQR) +#define DORMHR_F77 F77_FUNC(dormhr,DORMHR) +#define DORMQR_F77 F77_FUNC(dormqr,DORMQR) +#define DTREVC_F77 F77_FUNC(dtrevc,DTREVC) +#define DTREXC_F77 F77_FUNC(dtrexc,DTREXC) +#define DGEES_F77 F77_FUNC(dgees,DGEES) +#define DSPEV_F77 F77_FUNC(dspev,DSPEV) +#define DSYEV_F77 F77_FUNC(dsyev,DSYEV) +#define DSYGV_F77 F77_FUNC(dsygv,DSYGV) +#define DSTEQR_F77 F77_FUNC(dsteqr,DSTEQR) +#define DLAPY2_F77 F77_FUNC(dlapy2,DLAPY2) +#define DLARTG_F77 F77_FUNC(dlartg,DLARTG) +#define DLARFG_F77 F77_FUNC(dlarfg,DLARFG) +#define DLARND_F77 F77_FUNC(dlarnd,DLARND) +#define DLARNV_F77 F77_FUNC(dlarnv,DLARNV) +#define ILAENV_F77 F77_FUNC(ilaenv,ILAENV) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZGEQRF_F77 F77_FUNC(zgeqrf,ZGEQRF) +#define ZUNGQR_F77 F77_FUNC(zungqr,ZUNGQR) +#define ZGETRF_F77 F77_FUNC(zgetrf,ZGETRF) +#define ZGETRS_F77 F77_FUNC(zgetrs,ZGETRS) +#define ZGTTRF_F77 F77_FUNC(zgttrf,ZGTTRF) +#define ZGTTRS_F77 F77_FUNC(zgttrs,ZGTTRS) +#define ZPTTRF_F77 F77_FUNC(zpttrf,ZPTTRF) +#define ZPTTRS_F77 F77_FUNC(zpttrs,ZPTTRS) +#define ZGETRI_F77 F77_FUNC(zgetri,ZGETRI) +#define ZGERFS_F77 F77_FUNC(zgerfs,ZGERFS) +#define ZGECON_F77 F77_FUNC(zgecon,ZGECON) +#define ZGESVX_F77 F77_FUNC(zgesvx,ZGESVX) +#define ZGESV_F77 F77_FUNC(zgesv,ZGESV) +#define ZGEEQU_F77 F77_FUNC(zgeequ,ZGEEQU) +#define ZPOTRF_F77 F77_FUNC(zpotrf,ZPOTRF) +#define ZPOTRS_F77 F77_FUNC(zpotrs,ZPOTRS) +#define ZPOTRI_F77 F77_FUNC(zpotri,ZPOTRI) +#define ZPOCON_F77 F77_FUNC(zpocon,ZPOCON) +#define ZPOSV_F77 F77_FUNC(zposv,ZPOSV) +#define ZPOEQU_F77 F77_FUNC(zpoequ,ZPOEQU) +#define ZPORFS_F77 F77_FUNC(zporfs,ZPORFS) +#define ZPOSVX_F77 F77_FUNC(zposvx,ZPOSVX) +#define ZTRTRS_F77 F77_FUNC(ztrtrs,ZTRTRS) +#define ZGELS_F77 F77_FUNC(zgels,ZGELS) +#define ZGEEV_F77 F77_FUNC(zgeev,ZGEEV) +//#define ZGGEVX_F77 F77_FUNC(zggevx,ZGGEVX) +#define ZGEHRD_F77 F77_FUNC(zgehrd,ZGEHRD) +#define ZHSEQR_F77 F77_FUNC(zhseqr,ZHSEQR) +#define ZTREVC_F77 F77_FUNC(ztrevc,ZTREVC) +#define ZTREXC_F77 F77_FUNC(ztrexc,ZTREXC) +#define ZGEES_F77 F77_FUNC(zgees,ZGEES) +#define ZSTEQR_F77 F77_FUNC(zsteqr,ZSTEQR) +#define ZHEEV_F77 F77_FUNC(zheev,ZHEEV) +#define ZHEGV_F77 F77_FUNC(zhegv,ZHEGV) +#define ZLARTG_F77 F77_FUNC(zlartg,ZLARTG) +#define ZLARFG_F77 F77_FUNC(zlarfg,ZLARFG) +#define ZLARND_F77 F77_FUNC(zlarnd,ZLARND) +#define ZLARNV_F77 F77_FUNC(zlarnv,ZLARNV) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#elif defined(INTEL_MKL) + +#define PREFIX +#define Teuchos_fcd const char * + +#define DGEQRF_F77 F77_FUNC(dgeqrf,DGEQRF) +#define DGETRF_F77 F77_FUNC(dgetrf,DGETRF) +#define DGETRS_F77 F77_FUNC(dgetrs,DGETRS) +#define DGTTRF_F77 F77_FUNC(dgttrf,DGTTRF) +#define DGTTRS_F77 F77_FUNC(dgttrs,DGTTRS) +#define DPTTRF_F77 F77_FUNC(dpttrf,DPTTRF) +#define DPTTRS_F77 F77_FUNC(dpttrs,DPTTRS) +#define DGETRI_F77 F77_FUNC(dgetri,DGETRI) +#define DGERFS_F77 F77_FUNC(dgerfs,DGERFS) +#define DGECON_F77 F77_FUNC(dgecon,DGECON) +#define DGESVX_F77 F77_FUNC(dgesvx,DGESVX) +#define DGESV_F77 F77_FUNC(dgesv,DGESV) +#define DGEEQU_F77 F77_FUNC(dgeequ,DGEEQU) +#define DSYTRD_F77 F77_FUNC(dsytrd,DSYTRD) +#define DPOTRF_F77 F77_FUNC(dpotrf,DPOTRF) +#define DPOTRS_F77 F77_FUNC(dpotrs,DPOTRS) +#define DPOTRI_F77 F77_FUNC(dpotri,DPOTRI) +#define DPOCON_F77 F77_FUNC(dpocon,DPOCON) +#define DPOSV_F77 F77_FUNC(dposv,DPOSV) +#define DPOEQU_F77 F77_FUNC(dpoequ,DPOEQU) +#define DPORFS_F77 F77_FUNC(dporfs,DPORFS) +#define DPOSVX_F77 F77_FUNC(dposvx,DPOSVX) +#define DTRTRS_F77 F77_FUNC(dtrtrs,DTRTRS) +#define DLAMCH_F77 F77_FUNC(dlamch,DLAMCH) +#define DGELS_F77 F77_FUNC(dgels,DGELS) +#define DGEEV_F77 F77_FUNC(dgeev,DGEEV) +#define DGGEVX_F77 F77_FUNC(dggevx,DGGEVX) +#define DGEHRD_F77 F77_FUNC(dgehrd,DGEHRD) +#define DHSEQR_F77 F77_FUNC(dhseqr,DHSEQR) +#define DORGHR_F77 F77_FUNC(dorghr,DORGHR) +#define DORGQR_F77 F77_FUNC(dorgqr,DORGQR) +#define DORMHR_F77 F77_FUNC(dormhr,DORMHR) +#define DORMQR_F77 F77_FUNC(dormqr,DORMQR) +#define DTREVC_F77 F77_FUNC(dtrevc,DTREVC) +#define DTREXC_F77 F77_FUNC(dtrexc,DTREXC) +#define DGEES_F77 F77_FUNC(dgees,DGEES) +#define DSPEV_F77 F77_FUNC(dspev,DSPEV) +#define DSYEV_F77 F77_FUNC(dsyev,DSYEV) +#define DSYGV_F77 F77_FUNC(dsygv,DSYGV) +#define DSTEQR_F77 F77_FUNC(dsteqr,DSTEQR) +#define DLAPY2_F77 F77_FUNC(dlapy2,DLAPY2) +#define DLARTG_F77 F77_FUNC(dlartg,DLARTG) +#define DLARFG_F77 F77_FUNC(dlarfg,DLARFG) +#define DLARND_F77 F77_FUNC(dlarnd,DLARND) +#define DLARNV_F77 F77_FUNC(dlarnv,DLARNV) +#define ILAENV_F77 F77_FUNC(ilaenv,ILAENV) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZGEQRF_F77 F77_FUNC(zgeqrf,ZGEQRF) +#define ZUNGQR_F77 F77_FUNC(zungqr,ZUNGQR) +#define ZGTTRF_F77 F77_FUNC(zgttrf,ZGTTRF) +#define ZGTTRS_F77 F77_FUNC(zgttrs,ZGTTRS) +#define ZPTTRF_F77 F77_FUNC(zpttrf,ZPTTRF) +#define ZPTTRS_F77 F77_FUNC(zpttrs,ZPTTRS) +#define ZGETRF_F77 F77_FUNC(zgetrf,ZGETRF) +#define ZGETRS_F77 F77_FUNC(zgetrs,ZGETRS) +#define ZGETRI_F77 F77_FUNC(zgetri,ZGETRI) +#define ZGERFS_F77 F77_FUNC(zgerfs,ZGERFS) +#define ZGECON_F77 F77_FUNC(zgecon,ZGECON) +#define ZGESVX_F77 F77_FUNC(zgesvx,ZGESVX) +#define ZGESV_F77 F77_FUNC(zgesv,ZGESV) +#define ZGEEQU_F77 F77_FUNC(zgeequ,ZGEEQU) +#define ZPOTRF_F77 F77_FUNC(zpotrf,ZPOTRF) +#define ZPOTRS_F77 F77_FUNC(zpotrs,ZPOTRS) +#define ZPOTRI_F77 F77_FUNC(zpotri,ZPOTRI) +#define ZPOCON_F77 F77_FUNC(zpocon,ZPOCON) +#define ZPOSV_F77 F77_FUNC(zposv,ZPOSV) +#define ZPOEQU_F77 F77_FUNC(zpoequ,ZPOEQU) +#define ZPORFS_F77 F77_FUNC(zporfs,ZPORFS) +#define ZPOSVX_F77 F77_FUNC(zposvx,ZPOSVX) +#define ZTRTRS_F77 F77_FUNC(ztrtrs,ZTRTRS) +#define ZGELS_F77 F77_FUNC(zgels,ZGELS) +#define ZGEEV_F77 F77_FUNC(zgeev,ZGEEV) +//#define ZGGEVX_F77 F77_FUNC(zggevx,ZGGEVX) +#define ZGEHRD_F77 F77_FUNC(zgehrd,ZGEHRD) +#define ZHSEQR_F77 F77_FUNC(zhseqr,ZHSEQR) +#define ZTREVC_F77 F77_FUNC(ztrevc,ZTREVC) +#define ZTREXC_F77 F77_FUNC(ztrexc,ZTREXC) +#define ZGEES_F77 F77_FUNC(zgees,ZGEES) +#define ZSTEQR_F77 F77_FUNC(zsteqr,ZSTEQR) +#define ZHEEV_F77 F77_FUNC(zheev,ZHEEV) +#define ZHEGV_F77 F77_FUNC(zhegv,ZHEGV) +#define ZLARTG_F77 F77_FUNC(zlartg,ZLARTG) +#define ZLARFG_F77 F77_FUNC(zlarfg,ZLARFG) +#define ZLARND_F77 F77_FUNC(zlarnd,ZLARND) +#define ZLARNV_F77 F77_FUNC(zlarnv,ZLARNV) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#endif /* defined(CRAY_T3X) || defined(INTEL_CXML) || defined(INTEL_MKL) */ + +/* All three of these machines use a simple uppercase mangling of Fortran names */ + +/* if F77_FUNC is defined undefine it because we want to redefine */ + +#ifdef F77_FUNC +#undef F77_FUNC +#endif + +#define F77_FUNC(lcase,UCASE) PREFIX UCASE + +#else /* Define Teuchos_fcd for all other machines */ + +#define PREFIX +#define Teuchos_fcd const char * + +#ifndef HAVE_CONFIG_H + +#ifdef F77_FUNC +#undef F77_FUNC +#endif + +#ifdef TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE +#define F77_FUNC(lcase,UCASE) lcase +#else /* TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE not defined*/ +#define F77_FUNC(lcase,UCASE) lcase ## _ +#endif /* TRILINOS_HAVE_NO_FORTRAN_UNDERSCORE */ + +#endif /* HAVE_CONFIG_H */ + +#define DGEQRF_F77 F77_FUNC(dgeqrf,DGEQRF) +#define DGETRF_F77 F77_FUNC(dgetrf,DGETRF) +#define DGETRS_F77 F77_FUNC(dgetrs,DGETRS) +#define DGTTRF_F77 F77_FUNC(dgttrf,DGTTRF) +#define DGTTRS_F77 F77_FUNC(dgttrs,DGTTRS) +#define DPTTRF_F77 F77_FUNC(dpttrf,DPTTRF) +#define DPTTRS_F77 F77_FUNC(dpttrs,DPTTRS) +#define DGETRI_F77 F77_FUNC(dgetri,DGETRI) +#define DGERFS_F77 F77_FUNC(dgerfs,DGERFS) +#define DGECON_F77 F77_FUNC(dgecon,DGECON) +#define DGESVX_F77 F77_FUNC(dgesvx,DGESVX) +#define DGESV_F77 F77_FUNC(dgesv,DGESV) +#define DGEEQU_F77 F77_FUNC(dgeequ,DGEEQU) +#define DSYTRD_F77 F77_FUNC(dsytrd,DSYTRD) +#define DPOTRF_F77 F77_FUNC(dpotrf,DPOTRF) +#define DPOTRS_F77 F77_FUNC(dpotrs,DPOTRS) +#define DPOTRI_F77 F77_FUNC(dpotri,DPOTRI) +#define DPOCON_F77 F77_FUNC(dpocon,DPOCON) +#define DPOSV_F77 F77_FUNC(dposv,DPOSV) +#define DPOEQU_F77 F77_FUNC(dpoequ,DPOEQU) +#define DPORFS_F77 F77_FUNC(dporfs,DPORFS) +#define DPOSVX_F77 F77_FUNC(dposvx,DPOSVX) +#define DTRTRS_F77 F77_FUNC(dtrtrs,DTRTRS) +#define DLAMCH_F77 F77_FUNC(dlamch,DLAMCH) +#define DGELS_F77 F77_FUNC(dgels,DGELS) +#define DGEEV_F77 F77_FUNC(dgeev,DGEEV) +#define DGGEVX_F77 F77_FUNC(dggevx,DGGEVX) +#define DGEHRD_F77 F77_FUNC(dgehrd,DGEHRD) +#define DHSEQR_F77 F77_FUNC(dhseqr,DHSEQR) +#define DORGHR_F77 F77_FUNC(dorghr,DORGHR) +#define DORGQR_F77 F77_FUNC(dorgqr,DORGQR) +#define DORMHR_F77 F77_FUNC(dormhr,DORMHR) +#define DORMQR_F77 F77_FUNC(dormqr,DORMQR) +#define DTREVC_F77 F77_FUNC(dtrevc,DTREVC) +#define DTREXC_F77 F77_FUNC(dtrexc,DTREXC) +#define DGEES_F77 F77_FUNC(dgees,DGEES) +#define DSPEV_F77 F77_FUNC(dspev,DSPEV) +#define DSYEV_F77 F77_FUNC(dsyev,DSYEV) +#define DSYGV_F77 F77_FUNC(dsygv,DSYGV) +#define DSTEQR_F77 F77_FUNC(dsteqr,DSTEQR) +#define DLAPY2_F77 F77_FUNC(dlapy2,DLAPY2) +#define DLARND_F77 F77_FUNC(dlarnd,DLARND) +#define DLARNV_F77 F77_FUNC(dlarnv,DLARNV) +#define DLARTG_F77 F77_FUNC(dlartg,DLARTG) +#define DLARFG_F77 F77_FUNC(dlarfg,DLARFG) +#define ILAENV_F77 F77_FUNC(ilaenv,ILAENV) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define ZGEQRF_F77 F77_FUNC(zgeqrf,ZGEQRF) +#define ZUNGQR_F77 F77_FUNC(zungqr,ZUNGQR) +#define ZGETRF_F77 F77_FUNC(zgetrf,ZGETRF) +#define ZGETRS_F77 F77_FUNC(zgetrs,ZGETRS) +#define ZGTTRF_F77 F77_FUNC(zgttrf,ZGTTRF) +#define ZGTTRS_F77 F77_FUNC(zgttrs,ZGTTRS) +#define ZPTTRF_F77 F77_FUNC(zpttrf,ZPTTRF) +#define ZPTTRS_F77 F77_FUNC(zpttrs,ZPTTRS) +#define ZGETRI_F77 F77_FUNC(zgetri,ZGETRI) +#define ZGERFS_F77 F77_FUNC(zgerfs,ZGERFS) +#define ZGECON_F77 F77_FUNC(zgecon,ZGECON) +#define ZGESVX_F77 F77_FUNC(zgesvx,ZGESVX) +#define ZGESV_F77 F77_FUNC(zgesv,ZGESV) +#define ZGEEQU_F77 F77_FUNC(zgeequ,ZGEEQU) +#define ZPOTRF_F77 F77_FUNC(zpotrf,ZPOTRF) +#define ZPOTRS_F77 F77_FUNC(zpotrs,ZPOTRS) +#define ZPOTRI_F77 F77_FUNC(zpotri,ZPOTRI) +#define ZPOCON_F77 F77_FUNC(zpocon,ZPOCON) +#define ZPOSV_F77 F77_FUNC(zposv,ZPOSV) +#define ZPOEQU_F77 F77_FUNC(zpoequ,ZPOEQU) +#define ZPORFS_F77 F77_FUNC(zporfs,ZPORFS) +#define ZPOSVX_F77 F77_FUNC(zposvx,ZPOSVX) +#define ZTRTRS_F77 F77_FUNC(ztrtrs,ZTRTRS) +#define ZGELS_F77 F77_FUNC(zgels,ZGELS) +#define ZGEEV_F77 F77_FUNC(zgeev,ZGEEV) +//#define ZGGEVX_F77 F77_FUNC(zggevx,ZGGEVX) +#define ZGEHRD_F77 F77_FUNC(zgehrd,ZGEHRD) +#define ZHSEQR_F77 F77_FUNC(zhseqr,ZHSEQR) +#define ZTREVC_F77 F77_FUNC(ztrevc,ZTREVC) +#define ZTREXC_F77 F77_FUNC(ztrexc,ZTREXC) +#define ZGEES_F77 F77_FUNC(zgees,ZGEES) +#define ZSTEQR_F77 F77_FUNC(zsteqr,ZSTEQR) +#define ZHEEV_F77 F77_FUNC(zheev,ZHEEV) +#define ZHEGV_F77 F77_FUNC(zhegv,ZHEGV) +#define ZLARTG_F77 F77_FUNC(zlartg,ZLARTG) +#define ZLARFG_F77 F77_FUNC(zlarfg,ZLARFG) +#define ZLARND_F77 F77_FUNC(zlarnd,ZLARND) +#define ZLARNV_F77 F77_FUNC(zlarnv,ZLARNV) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#endif + +#define SGEQRF_F77 F77_FUNC(sgeqrf,SGEQRF) +#define SGETRF_F77 F77_FUNC(sgetrf,SGETRF) +#define SGETRS_F77 F77_FUNC(sgetrs,SGETRS) +#define SGTTRF_F77 F77_FUNC(sgttrf,SGTTRF) +#define SGTTRS_F77 F77_FUNC(sgttrs,SGTTRS) +#define SPTTRF_F77 F77_FUNC(spttrf,SPTTRF) +#define SPTTRS_F77 F77_FUNC(spttrs,SPTTRS) +#define SGETRI_F77 F77_FUNC(sgetri,SGETRI) +#define SGERFS_F77 F77_FUNC(sgerfs,SGERFS) +#define SGECON_F77 F77_FUNC(sgecon,SGECON) +#define SGESVX_F77 F77_FUNC(sgesvx,SGESVX) +#define SGESV_F77 F77_FUNC(sgesv,SGESV) +#define SGEEQU_F77 F77_FUNC(sgeequ,SGEEQU) +#define SSYTRD_F77 F77_FUNC(ssytrd,SSYTRD) +#define SPOTRF_F77 F77_FUNC(spotrf,SPOTRF) +#define SPOTRS_F77 F77_FUNC(spotrs,SPOTRS) +#define SPOTRI_F77 F77_FUNC(spotri,SPOTRI) +#define SPOCON_F77 F77_FUNC(spocon,SPOCON) +#define SPOSV_F77 F77_FUNC(sposv,SPOSV) +#define SPOEQU_F77 F77_FUNC(spoequ,SPOEQU) +#define SPORFS_F77 F77_FUNC(sporfs,SPORFS) +#define SPOSVX_F77 F77_FUNC(sposvx,SPOSVX) +#define STRTRS_F77 F77_FUNC(strtrs,STRTRS) +#define SGELS_F77 F77_FUNC(sgels,SGELS) +#define SGEEV_F77 F77_FUNC(sgeev,SGEEV) +#define SGGEVX_F77 F77_FUNC(sggevx,SGGEVX) +#define SGEHRD_F77 F77_FUNC(sgehrd,SGEHRD) +#define SHSEQR_F77 F77_FUNC(shseqr,SHSEQR) +#define SORGHR_F77 F77_FUNC(sorghr,SORGHR) +#define SORGQR_F77 F77_FUNC(sorgqr,SORGQR) +#define SORMHR_F77 F77_FUNC(sormhr,SORMHR) +#define SORMQR_F77 F77_FUNC(sormqr,SORMQR) +#define STREVC_F77 F77_FUNC(strevc,STREVC) +#define STREXC_F77 F77_FUNC(strexc,STREXC) +#define SLAMCH_F77 F77_FUNC(slamch,SLAMCH) +#define SGEES_F77 F77_FUNC(sgees,SGEES) +#define SSPEV_F77 F77_FUNC(sspev,SSPEV) +#define SSYEV_F77 F77_FUNC(ssyev,SSYEV) +#define SSYGV_F77 F77_FUNC(ssygv,SSYGV) +#define SSTEQR_F77 F77_FUNC(ssteqr,SSTEQR) +#define SLAPY2_F77 F77_FUNC(slapy2,SLAPY2) +#define SLARTG_F77 F77_FUNC(slartg,SLARTG) +#define SLARFG_F77 F77_FUNC(slarfg,SLARFG) +#define SLARND_F77 F77_FUNC(slarnd,SLARND) +#define SLARNV_F77 F77_FUNC(slarnv,SLARNV) + +#ifdef HAVE_TEUCHOS_COMPLEX + +#define CGEQRF_F77 F77_FUNC(cgeqrf,CGEQRF) +#define CUNGQR_F77 F77_FUNC(cungqr,CUNGQR) +#define CGETRF_F77 F77_FUNC(cgetrf,CGETRF) +#define CGETRS_F77 F77_FUNC(cgetrs,CGETRS) +#define CGTTRF_F77 F77_FUNC(cgttrf,CGTTRF) +#define CGTTRS_F77 F77_FUNC(cgttrs,CGTTRS) +#define CPTTRF_F77 F77_FUNC(cpttrf,CPTTRF) +#define CPTTRS_F77 F77_FUNC(cpttrs,CPTTRS) +#define CGETRI_F77 F77_FUNC(cgetri,CGETRI) +#define CGERFS_F77 F77_FUNC(cgerfs,CGERFS) +#define CGECON_F77 F77_FUNC(cgecon,CGECON) +#define CGESVX_F77 F77_FUNC(cgesvx,CGESVX) +#define CGESV_F77 F77_FUNC(cgesv,CGESV) +#define CGEEQU_F77 F77_FUNC(cgeequ,CGEEQU) +#define CPOTRF_F77 F77_FUNC(cpotrf,CPOTRF) +#define CPOTRS_F77 F77_FUNC(cpotrs,CPOTRS) +#define CPOTRI_F77 F77_FUNC(cpotri,CPOTRI) +#define CPOCON_F77 F77_FUNC(cpocon,CPOCON) +#define CPOSV_F77 F77_FUNC(cposv,CPOSV) +#define CPOEQU_F77 F77_FUNC(cpoequ,CPOEQU) +#define CPORFS_F77 F77_FUNC(cporfs,CPORFS) +#define CPOSVX_F77 F77_FUNC(cposvx,CPOSVX) +#define CTRTRS_F77 F77_FUNC(ctrtrs,CTRTRS) +#define CGELS_F77 F77_FUNC(cgels,CGELS) +#define CGEEV_F77 F77_FUNC(cgeev,CGEEV) +//#define CGGEVX_F77 F77_FUNC(cggevx,CGGEVX) +#define CGEHRD_F77 F77_FUNC(cgehrd,CGEHRD) +#define CHSEQR_F77 F77_FUNC(chseqr,CHSEQR) +#define CTREVC_F77 F77_FUNC(ctrevc,CTREVC) +#define CTREXC_F77 F77_FUNC(ctrexc,CTREXC) +#define CGEES_F77 F77_FUNC(cgees,CGEES) +#define CSTEQR_F77 F77_FUNC(csteqr,CSTEQR) +#define CHEEV_F77 F77_FUNC(cheev,CHEEV) +#define CHEGV_F77 F77_FUNC(chegv,CHEGV) +#define CLARTG_F77 F77_FUNC(clartg,CLARTG) +#define CLARFG_F77 F77_FUNC(clarfg,CLARFG) +#define CLARND_F77 F77_FUNC(clarnd,CLARND) +#define CLARNV_F77 F77_FUNC(clarnv,CLARNV) + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#ifdef __cplusplus +extern "C" { +#endif + +// Double precision LAPACK linear solvers +void PREFIX DGELS_F77(Teuchos_fcd ch, const int* m, const int* n, const int* nrhs, double* a, const int* lda, double* b, const int* ldb, double* work, const int* lwork, int* info); +void PREFIX DGEQRF_F77(const int* m, const int* n, double* a, const int* lda, double* tau, double* work, const int* lwork, int* info); +void PREFIX DGETRF_F77(const int* m, const int* n, double* a, const int* lda, int* ipiv, int* info); +void PREFIX DGETRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const double* a, const int* lda,const int* ipiv, double* x , const int* ldx, int* info); +void PREFIX DGTTRF_F77(const int* n, double* dl, double* d, double* du, double* du2, int* ipiv, int* info); +void PREFIX DGTTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const double* dl, const double* d, const double* du, const double* du2, const int* ipiv, double* x , const int* ldx, int* info); +void PREFIX DPTTRF_F77(const int* n, double* d, double* e, int* info); +void PREFIX DPTTRS_F77(const int* n, const int* nrhs, const double* d, const double* e, double* x , const int* ldx, int* info); +void PREFIX DGETRI_F77(const int* n, double* a, const int* lda, const int* ipiv, double* work , const int* lwork, int* info); +void PREFIX DGECON_F77(Teuchos_fcd norm, const int* n, const double* a, const int* lda, const double* anorm, double* rcond, double* work, int* iwork, int* info); +void PREFIX DGESV_F77(const int* n, const int* nrhs, double* a, const int* lda, int* ipiv, double* x , const int* ldx, int* info); +void PREFIX DGEEQU_F77(const int* m, const int* n, const double* a, const int* lda, double* r, double* c, double* rowcnd, double* colcnd, double* amax, int* info); +void PREFIX DGERFS_F77(Teuchos_fcd, const int* n, const int* nrhs, const double* a, const int* lda, const double* af, const int* ldaf, const int* ipiv, const double* b, const int* ldb, double* x, const int* ldx, double* ferr, double* berr, double* work, int* iwork, int* info); +void PREFIX DGESVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, double* a, const int* lda, double* af, const int* ldaf, int* ipiv, Teuchos_fcd, double* r, +double* c, double* b, const int* ldb, double* x, const int* ldx, double* rcond, double* ferr, double* berr, double* work, int* iwork, int* info); +void PREFIX DSYTRD_F77(Teuchos_fcd, const int* n, double* a, const int* lda, double* D, double* E, double* tau, double* work, const int* lwork, int* info); +void PREFIX DPOTRF_F77(Teuchos_fcd, const int* n, double* a, const int* lda, int* info); +void PREFIX DPOTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const double* a, const int* lda, double*x , const int* ldx, int* info); +void PREFIX DPOTRI_F77(Teuchos_fcd, const int* n, double* a, const int* lda, int* info); +void PREFIX DPOCON_F77(Teuchos_fcd, const int* n, const double* a, const int* lda, const double* anorm, double* rcond, double* work, int* iwork, int* info); +void PREFIX DPOSV_F77(Teuchos_fcd, const int* n, const int* nrhs, double* a, const int* lda, double*x , const int* ldx, int* info); +void PREFIX DPOEQU_F77(const int* n, const double* a, const int* lda, double* s, double* scond, double* amax, int* info); +void PREFIX DPORFS_F77(Teuchos_fcd, const int* n, const int* nrhs, double* a, const int* lda, const double* af, const int* ldaf, const double* b, const int* ldb, double* x, const int* ldx, double* ferr, double* berr, double* work, int* iwork, int* info); +void PREFIX DPOSVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, double* a, const int* lda, double* af, const int* ldaf, Teuchos_fcd, double* s, double* b, const int* ldb, double* x, const int* ldx, double* rcond, double* ferr, double* berr, double* work, int* iwork, int* info); +void PREFIX DTRTRS_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, double* a, const int* lda, double* b, const int* ldb, int* info); + +// Single precision LAPACK linear solvers + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +void PREFIX SGELS_F77(Teuchos_fcd ch, const int* m, const int* n, const int* nrhs, float* a, const int* lda, float* b, const int* ldb, float* work, const int* lwork, int* info); +void PREFIX SGEQRF_F77(const int* m, const int* n, float* a, const int* lda, float* tau, float* work, const int* lwork, int* info); +void PREFIX SGETRF_F77(const int* m, const int* n, float* a, const int* lda, int* ipiv, int* info); +void PREFIX SGETRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const float* a, const int* lda,const int* ipiv, float* x , const int* ldx, int* info); +void PREFIX SGTTRF_F77(const int* n, float* dl, float* d, float* du, float* du2, int* ipiv, int* info); +void PREFIX SGTTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const float* dl, const float* d, const float* du, const float* du2, const int* ipiv, float* x , const int* ldx, int* info); +void PREFIX SPTTRF_F77(const int* n, float* d, float* e, int* info); +void PREFIX SPTTRS_F77(const int* n, const int* nrhs, const float* d, const float* e, float* x , const int* ldx, int* info); +void PREFIX SGETRI_F77(const int* n, float* a, const int* lda, const int* ipiv, float* work , const int* lwork, int* info); +void PREFIX SGECON_F77(Teuchos_fcd norm, const int* n, const float* a, const int* lda, const float* anorm, float* rcond, float* work, int* iwork, int* info); +void PREFIX SGESV_F77(const int* n, const int* nrhs, float* a, const int* lda, int* ipiv, float* x , const int* ldx, int* info); +void PREFIX SGEEQU_F77(const int* m, const int* n, const float* a, const int* lda, float* r, float* c, float* rowcnd, float* colcnd, float* amax, int* info); +void PREFIX SGERFS_F77(Teuchos_fcd, const int* n, const int* nrhs, const float* a, const int* lda, const float* af, const int* ldaf, const int* ipiv, const float* b, const int* ldb, float* x, const int* ldx, float* ferr, float* berr, float* work, int* iwork, int* info); +void PREFIX SGESVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, float* a, const int* lda, float* af, const int* ldaf, int* ipiv, Teuchos_fcd, float* r, +float* c, float* b, const int* ldb, float* x, const int* ldx, float* rcond, float* ferr, float* berr, float* work, int* iwork, int* info); +void PREFIX SSYTRD_F77(Teuchos_fcd, const int* n, float* a, const int* lda, float* D, float* E, float* tau, float* work, const int* lwork, int* info); +void PREFIX SPOTRF_F77(Teuchos_fcd, const int* n, float* a, const int* lda, int* info); +void PREFIX SPOTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const float* a, const int* lda, float*x , const int* ldx, int* info); +void PREFIX SPOTRI_F77(Teuchos_fcd, const int* n, float* a, const int* lda, int* info); +void PREFIX SPOCON_F77(Teuchos_fcd, const int* n, const float* a, const int* lda, const float* anorm, float* rcond, float* work, int* iwork, int* info); +void PREFIX SPOSV_F77(Teuchos_fcd, const int* n, const int* nrhs, float* a, const int* lda, float*x , const int* ldx, int* info); +void PREFIX SPOEQU_F77(const int* n, const float* a, const int* lda, float* s, float* scond, float* amax, int* info); +void PREFIX SPORFS_F77(Teuchos_fcd, const int* n, const int* nrhs, float* a, const int* lda, const float* af, const int* ldaf, const float* b, const int* ldb, float* x, const int* ldx, float* ferr, float* berr, float* work, int* iwork, int* info); +void PREFIX SPOSVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, float* a, const int* lda, float* af, const int* ldaf, Teuchos_fcd, float* s, float* b, const int* ldb, float* x, const int* ldx, float* rcond, float* ferr, float* berr, float* work, int* iwork, int* info); +void PREFIX STRTRS_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, float* a, const int* lda, float* b, const int* ldb, int* info); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +// Double precision LAPACK eigen solvers +void PREFIX DSPEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, double* ap, double* w, double* z, const int* ldz, double* work, int* info); +void PREFIX DSYEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, double* a, const int* lda, double* w, double* work, const int* lwork, int* info); +void PREFIX DSYGV_F77(const int* itype, Teuchos_fcd, Teuchos_fcd, const int* n, double* a, const int* lda, double* B, const int* ldb, double* w, double* work, const int* lwork, int* info); +void PREFIX DSTEQR_F77(Teuchos_fcd, const int* n, double* D, double* E, double* Z, const int* ldz, double* work, int* info); +void PREFIX DGEEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, double* a, const int* lda, double* wr, double* wi, double* vl, const int* ldvl, double* vr, const int* ldvr, double* work, const int* lwork, int* info); +void PREFIX DGGEVX_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, double* a, const int* lda, double* b, const int* ldb, double* alphar, double* alphai, double* beta, double* vl, const int* ldvl, double* vr, const int* ldvr, int* ilo, int* ihi, double* lscale, double* rscale, double* abnrm, double* bbnrm, double* rconde, double* rcondv, double* work, const int* lwork, int* iwork, int* bwork, int* info); +void PREFIX DGEHRD_F77(const int* n, const int* ilo, const int* ihi, double* A, const int* lda, double* tau, double* work, const int* lwork, int* info); +void PREFIX DHSEQR_F77(Teuchos_fcd job, Teuchos_fcd, const int* n, const int* ilo, const int* ihi, double* h, const int* ldh, double* wr, double* wi, double* z, const int* ldz, double* work, const int* lwork, int* info); +void PREFIX DGEES_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(double*, double*), const int* n, double* a, const int* lda, int*sdim, double* wr, double* wi, double* vs, const int* ldvs, double* work, const int* lwork, int* bwork, int* info); +void PREFIX DORGHR_F77(const int* n, const int* ilo, const int* ihi, double* a, const int* lda, double* tau, double* work, int* lwork, int* info); +void PREFIX DORMHR_F77(Teuchos_fcd, Teuchos_fcd, const int* m, const int* n, const int* ilo, const int* ihi, const double* a, const int* lda, const double* tau, double* c, const int* ldc, double* work, int* lwork, int* info); +void PREFIX DORGQR_F77(const int* m, const int* n, const int* k, double* a, const int* lda, const double* tau, double* work, const int* lwork, int* info); +void PREFIX DORMQR_F77(Teuchos_fcd, Teuchos_fcd, const int* m, const int* n, const int* k, double* a, const int* lda, const double* tau, double* C, const int* ldc, double* work, const int* lwork, int* info); +void PREFIX DTREVC_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(double*,double*), const int* n, const double* t, const int* ldt, double* vl, const int* ldvl, double* vr, const int* ldvr, const int* mm, int* m, double* work, int* info); +void PREFIX DTREXC_F77(Teuchos_fcd, const int* n, double* t, const int* ldt, double* q, const int* ldq, int* ifst, int* ilst, double* work, int* info); + +// Single precision LAPACK eigen solvers + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +void PREFIX SSPEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, float* ap, float* w, float* z, const int* ldz, float* work, int* info); +void PREFIX SSYEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, float* a, const int* lda, float* w, float* work, const int* lwork, int* info); +void PREFIX SSYGV_F77(const int* itype, Teuchos_fcd, Teuchos_fcd, const int* n, float* a, const int* lda, float* B, const int* ldb, float* w, float* work, const int* lwork, int* info); +void PREFIX SSTEQR_F77(Teuchos_fcd, const int* n, float* D, float* E, float* Z, const int* ldz, float* work, int* info); +void PREFIX SGEEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, float* a, const int* lda, float* wr, float* wi, float* vl, const int* ldvl, float* vr, const int* ldvr, float* work, const int* lwork, int* info); +void PREFIX SGGEVX_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, float* a, const int* lda, float* b, const int* ldb, float* alphar, float* alphai, float* beta, float* vl, const int* ldvl, float* vr, const int* ldvr, int* ilo, int* ihi, float* lscale, float* rscale, float* abnrm, float* bbnrm, float* rconde, float* rcondv, float* work, const int* lwork, int* iwork, int* bwork, int* info); +void PREFIX SGEHRD_F77(const int* n, const int* ilo, const int* ihi, float* A, const int* lda, float* tau, float* work, const int* lwork, int* info); +void PREFIX SHSEQR_F77(Teuchos_fcd job, Teuchos_fcd, const int* n, const int* ilo, const int* ihi, float* h, const int* ldh, float* wr, float* wi, float* z, const int* ldz, float* work, const int* lwork, int* info); +void PREFIX SGEES_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(float*, float*), const int* n, float* a, const int* lda, int* sdim, float* wr, float* wi, float* vs, const int* ldvs, float* work, const int* lwork, int* bwork, int* info); +void PREFIX SORGHR_F77(const int* n, const int* ilo, const int* ihi, float* a, const int* lda, float* tau, float* work, int* lwork, int* info); +void PREFIX SORMHR_F77(Teuchos_fcd, Teuchos_fcd, const int* m, const int* n, const int* ilo, const int* ihi, const float* a, const int* lda, const float* tau, float* c, const int* ldc, float* work, int* lwork, int* info); +void PREFIX SORGQR_F77(const int* m, const int* n, const int* k, float* a, const int* lda, const float* tau, float* work, const int* lwork, int* info); +void PREFIX SORMQR_F77(Teuchos_fcd, Teuchos_fcd, const int* m, const int* n, const int* k, float* a, const int* lda, const float* tau, float* C, const int* ldc, float* work, const int* lwork, int* info); +void PREFIX STREVC_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(float*,float*), const int* n, const float* t, const int* ldt, float* vl, const int* ldvl, float* vr, const int* ldvr, const int* mm, int* m, float* work, int* info); +void PREFIX STREXC_F77(Teuchos_fcd, const int* n, float* t, const int* ldt, float* q, const int* ldq, int* ifst, int* ilst, float* work, int* info); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +void PREFIX SLARTG_F77(const float* f, const float* g, float* c, float* s, float* r); +void PREFIX DLARTG_F77(const double* f, const double* g, double* c, double* s, double* r); + +void PREFIX SLARFG_F77(const int* n, float* alpha, float* x, const int* incx, float* tau); +void PREFIX DLARFG_F77(const int* n, double* alpha, double* x, const int* incx, double* tau); + +float PREFIX SLARND_F77(const int* idist, int* seed); +double PREFIX DLARND_F77(const int* idist, int* seed); + +void PREFIX SLARNV_F77(const int* idist, int* seed, const int* n, float* v); +void PREFIX DLARNV_F77(const int* idist, int* seed, const int* n, double* v); + +float PREFIX SLAMCH_F77(Teuchos_fcd); +double PREFIX DLAMCH_F77(Teuchos_fcd); + +#if defined(INTEL_CXML) +int PREFIX ILAENV_F77( const int* ispec, const char* name, unsigned int name_length, const char* opts, unsigned int opts_length, const int* N1, const int* N2, const int* N3, const int* N4 ); +#else +int PREFIX ILAENV_F77( const int* ispec, const char* name, const char* opts, const int* N1, const int* N2, const int* N3, const int* N4, unsigned int name_length, unsigned int opts_length ); +#endif + +float PREFIX SLAPY2_F77(const float* x, const float* y); +double PREFIX DLAPY2_F77(const double* x, const double* y); + +#ifdef HAVE_TEUCHOS_COMPLEX + +// Double precision std::complex LAPACK linear solvers +void PREFIX ZGELS_F77(Teuchos_fcd ch, const int* m, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* b, const int* ldb, std::complex* work, const int* lwork, int* info); +void PREFIX ZGEQRF_F77(const int* m, const int* n, std::complex* a, const int* lda, std::complex* tau, std::complex* work, const int* lwork, int* info); +void PREFIX ZUNGQR_F77(const int* m, const int* n, const int* k, std::complex* a, const int* lda, const std::complex* tau, std::complex* work, const int* lwork, int* info); +void PREFIX ZGETRF_F77(const int* m, const int* n, std::complex* a, const int* lda, int* ipiv, int* info); +void PREFIX ZGETRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* a, const int* lda,const int* ipiv, std::complex* x , const int* ldx, int* info); +void PREFIX ZGTTRF_F77(const int* n, std::complex* dl, std::complex* d, std::complex* du, std::complex* du2, int* ipiv, int* info); +void PREFIX ZGTTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* dl, const std::complex* d, const std::complex* du, const std::complex* du2, const int* ipiv, std::complex* x , const int* ldx, int* info); +void PREFIX ZPTTRF_F77(const int* n, std::complex* d, std::complex* e, int* info); +void PREFIX ZPTTRS_F77(const int* n, const int* nrhs, const std::complex* d, const std::complex* e, std::complex* x , const int* ldx, int* info); +void PREFIX ZGETRI_F77(const int* n, std::complex* a, const int* lda, const int* ipiv, std::complex* work , const int* lwork, int* info); +void PREFIX ZGECON_F77(Teuchos_fcd norm, const int* n, const std::complex* a, const int* lda, const double* anorm, double* rcond, std::complex* work, double* rwork, int* info); +void PREFIX ZGESV_F77(const int* n, const int* nrhs, std::complex* a, const int* lda, int* ipiv, std::complex* x , const int* ldx, int* info); +void PREFIX ZGEEQU_F77(const int* m, const int* n, const std::complex* a, const int* lda, double* r, double* c, double* rowcnd, double* colcnd, double* amax, int* info); +void PREFIX ZGERFS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* a, const int* lda, const std::complex* af, const int* ldaf, const int* ipiv, const std::complex* b, const int* ldb, std::complex* x, const int* ldx, double* ferr, double* berr, std::complex* work, double* iwork, int* info); +//void PREFIX ZGESVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* af, const int* ldaf, int* ipiv, Teuchos_fcd, double* r, double* c, std::complex* b, const int* ldb, std::complex* x, const int* ldx, double* rcond, double* ferr, double* berr, std::complex* work, double* iwork, int* info); +void PREFIX ZPOTRF_F77(Teuchos_fcd, const int* n, std::complex* a, const int* lda, int* info); +void PREFIX ZPOTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* a, const int* lda, std::complex*x , const int* ldx, int* info); +void PREFIX ZPOTRI_F77(Teuchos_fcd, const int* n, std::complex* a, const int* lda, int* info); +void PREFIX ZPOCON_F77(Teuchos_fcd, const int* n, const std::complex* a, const int* lda, const double* anorm, double* rcond, std::complex* work, double* rwork, int* info); +void PREFIX ZPOSV_F77(Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex*x , const int* ldx, int* info); +void PREFIX ZPOEQU_F77(const int* n, const std::complex* a, const int* lda, double* s, double* scond, double* amax, int* info); +void PREFIX ZPORFS_F77(Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, const std::complex* af, const int* ldaf, const std::complex* b, const int* ldb, std::complex* x, const int* ldx, double* ferr, double* berr, std::complex* work, double* rwork, int* info); +void PREFIX ZPOSVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* af, const int* ldaf, Teuchos_fcd, double* s, std::complex* b, const int* ldb, std::complex* x, const int* ldx, double* rcond, double* ferr, double* berr, std::complex* work, double* rwork, int* info); +void PREFIX ZTRTRS_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* b, const int* ldb, int* info); + +// Single precision std::complex LAPACK linear solvers + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +void PREFIX CGELS_F77(Teuchos_fcd ch, const int* m, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* b, const int* ldb, std::complex* work, const int* lwork, int* info); +void PREFIX CGEQRF_F77(const int* m, const int* n, std::complex* a, const int* lda, std::complex* tau, std::complex* work, const int* lwork, int* info); +void PREFIX CUNGQR_F77(const int* m, const int* n, const int* k, std::complex* a, const int* lda, const std::complex* tau, std::complex* work, const int* lwork, int* info); +void PREFIX CGETRF_F77(const int* m, const int* n, std::complex* a, const int* lda, int* ipiv, int* info); +void PREFIX CGETRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* a, const int* lda,const int* ipiv, std::complex* x , const int* ldx, int* info); +void PREFIX CGTTRF_F77(const int* n, std::complex* dl, std::complex* d, std::complex* du, std::complex* du2, int* ipiv, int* info); +void PREFIX CGTTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* dl, const std::complex* d, const std::complex* du, const std::complex* du2, const int* ipiv, std::complex* x , const int* ldx, int* info); +void PREFIX CPTTRF_F77(const int* n, std::complex* d, std::complex* e, int* info); +void PREFIX CPTTRS_F77(const int* n, const int* nrhs, const std::complex* d, const std::complex* e, std::complex* x , const int* ldx, int* info); +void PREFIX CGETRI_F77(const int* n, std::complex* a, const int* lda, const int* ipiv, std::complex* work , const int* lwork, int* info); +void PREFIX CGECON_F77(Teuchos_fcd norm, const int* n, const std::complex* a, const int* lda, const float* anorm, float* rcond, std::complex* work, float* rwork, int* info); +void PREFIX CGESV_F77(const int* n, const int* nrhs, std::complex* a, const int* lda, int* ipiv, std::complex* x, const int* ldx, int* info); +void PREFIX CGEEQU_F77(const int* m, const int* n, const std::complex* a, const int* lda, float* r, float* c, float* rowcnd, float* colcnd, float* amax, int* info); +void PREFIX CGERFS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* a, const int* lda, const std::complex* af, const int* ldaf, const int* ipiv, const std::complex* b, const int* ldb, std::complex* x, const int* ldx, float* ferr, float* berr, std::complex* work, float* rwork, int* info); +void PREFIX CGESVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* af, const int* ldaf, int* ipiv, Teuchos_fcd, float* r, float* c, std::complex* b, const int* ldb, std::complex* x, const int* ldx, float* rcond, float* ferr, float* berr, std::complex* work, float* rwork, int* info); +void PREFIX CPOTRF_F77(Teuchos_fcd, const int* n, std::complex* a, const int* lda, int* info); +void PREFIX CPOTRS_F77(Teuchos_fcd, const int* n, const int* nrhs, const std::complex* a, const int* lda, std::complex*x , const int* ldx, int* info); +void PREFIX CPOTRI_F77(Teuchos_fcd, const int* n, std::complex* a, const int* lda, int* info); +void PREFIX CPOCON_F77(Teuchos_fcd, const int* n, const std::complex* a, const int* lda, const float* anorm, float* rcond, std::complex* work, float* rwork, int* info); +void PREFIX CPOSV_F77(Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex*x , const int* ldx, int* info); +void PREFIX CPOEQU_F77(const int* n, const std::complex* a, const int* lda, float* s, float* scond, float* amax, int* info); +void PREFIX CPORFS_F77(Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, const std::complex* af, const int* ldaf, const std::complex* b, const int* ldb, std::complex* x, const int* ldx, float* ferr, float* berr, std::complex* work, float* rwork, int* info); +void PREFIX CPOSVX_F77(Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* af, const int* ldaf, Teuchos_fcd, float* s, std::complex* b, const int* ldb, std::complex* x, const int* ldx, float* rcond, float* ferr, float* berr, std::complex* work, float* rwork, int* info); +void PREFIX CTRTRS_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, const int* nrhs, std::complex* a, const int* lda, std::complex* b, const int* ldb, int* info); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +// Double precision std::complex LAPACK eigen solvers +void PREFIX ZSTEQR_F77(Teuchos_fcd, const int* n, double* D, double* E, std::complex* Z, const int* ldz, std::complex* work, int* info); +void PREFIX ZHEEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, double* w, std::complex* work, const int* lwork, double* rwork, int* info); +void PREFIX ZHEGV_F77(const int* itype, Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, std::complex* B, const int* ldb, double* w, std::complex* work, const int* lwork, double *rwork, int* info); +void PREFIX ZGEEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, std::complex* w, std::complex* vl, const int* ldvl, std::complex* vr, const int* ldvr, std::complex* work, const int* lwork, double* rwork, int* info); +//void PREFIX ZGGEVX_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, std::complex* b, const int* ldb, std::complex* alpha, std::complex* beta, std::complex* vl, const int* ldvl, std::complex* vr, const int* ldvr, int* ilo, int* ihi, double* lscale, double* rscale, double* abnrm, double* bbnrm, double* rconde, double* rcondv, std::complex* work, const int* lwork, int* iwork, int* bwork, int* info); +void PREFIX ZGEHRD_F77(const int* n, const int* ilo, const int* ihi, std::complex* A, const int* lda, std::complex* tau, std::complex* work, const int* lwork, int* info); +void PREFIX ZHSEQR_F77(Teuchos_fcd job, Teuchos_fcd, const int* n, const int* ilo, const int* ihi, std::complex* h, const int* ldh, std::complex* w, std::complex* z, const int* ldz, std::complex* work, const int* lwork, int* info); +void PREFIX ZGEES_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(std::complex*), const int* n, std::complex* a, const int* lda, int* sdim, std::complex* w, std::complex* vs, const int* ldvs, std::complex* work, const int* lwork, double* rwork, int* bwork, int* info); +void PREFIX ZTREVC_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(std::complex*), const int* n, const std::complex* t, const int* ldt, std::complex* vl, const int* ldvl, std::complex* vr, const int* ldvr, const int* mm, int* m, std::complex* work, double* rwork, int* info); +void PREFIX ZTREXC_F77(Teuchos_fcd, const int* n, std::complex* t, const int* ldt, std::complex* q, const int* ldq, int* ifst, int* ilst, int* info); + +// Single precision std::complex LAPACK eigen solvers + +#ifdef HAVE_TEUCHOS_BLASFLOAT + +void PREFIX CSTEQR_F77(Teuchos_fcd, const int* n, std::complex* D, std::complex* E, std::complex* Z, const int* ldz, std::complex* work, int* info); +void PREFIX CHEEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, float* w, std::complex* work, const int* lwork, float* rwork, int* info); +void PREFIX CHEGV_F77(const int* itype, Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, std::complex* B, const int* ldb, float* w, std::complex* work, const int* lwork, float *rwork, int* info); +void PREFIX CGEEV_F77(Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, std::complex* wr, std::complex* vl, const int* ldvl, std::complex* vr, const int* ldvr, std::complex* work, const int* lwork, float* rwork, int* info); +void PREFIX CGGEVX_F77(Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, Teuchos_fcd, const int* n, std::complex* a, const int* lda, std::complex* b, const int* ldb, std::complex* alpha, std::complex* beta, std::complex* vl, const int* ldvl, std::complex* vr, const int* ldvr, int* ilo, int* ihi, float* lscale, float* rscale, float* abnrm, float* bbnrm, float* rconde, float* rcondv, std::complex* work, const int* lwork, int* iwork, int* bwork, int* info); +void PREFIX CGEHRD_F77(const int* n, const int* ilo, const int* ihi, std::complex* A, const int* lda, std::complex* tau, std::complex* work, const int* lwork, int* info); +void PREFIX CHSEQR_F77(Teuchos_fcd job, Teuchos_fcd, const int* n, const int* ilo, const int* ihi, std::complex* h, const int* ldh, std::complex* w, std::complex* z, const int* ldz, std::complex* work, const int* lwork, int* info); +void PREFIX CGEES_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(std::complex*), const int* n, std::complex* a, const int* lda, int* sdim, std::complex* w, std::complex* vs, const int* ldvs, std::complex* work, const int* lwork, float* rwork, int* bwork, int* info); +void PREFIX CTREVC_F77(Teuchos_fcd, Teuchos_fcd, int (*ptr2func)(std::complex*), const int* n, const std::complex* t, const int* ldt, std::complex* vl, const int* ldvl, std::complex* vr, const int* ldvr, const int* mm, int* m, std::complex* work, float* rwork, int* info); +void PREFIX CTREXC_F77(Teuchos_fcd, const int* n, std::complex* t, const int* ldt, std::complex* q, const int* ldq, int* ifst, int* ilst, int* info); + +#endif // HAVE_TEUCHOS_BLASFLOAT + +void PREFIX CLARTG_F77(const std::complex* f, const std::complex* g, float* c, std::complex* s, std::complex* r); +void PREFIX ZLARTG_F77(const std::complex* f, const std::complex* g, double* c, std::complex* s, std::complex* r); + +void PREFIX CLARFG_F77(const int* n, std::complex* alpha, std::complex* x, const int* incx, std::complex* tau); +void PREFIX ZLARFG_F77(const int* n, std::complex* alpha, std::complex* x, const int* incx, std::complex* tau); + +std::complex PREFIX CLARND_F77(const int* idist, int* seed); +std::complex PREFIX ZLARND_F77(const int* idist, int* seed); + +void PREFIX CLARNV_F77(const int* idist, int* seed, const int* n, std::complex* v); +void PREFIX ZLARNV_F77(const int* idist, int* seed, const int* n, std::complex* v); + +#endif /* HAVE_TEUCHOS_COMPLEX */ + +#ifdef __cplusplus +} +#endif + +#endif // end of TEUCHOS_LAPACK_WRAPPERS_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_LabeledObject.hpp b/fastlib/trilinos/include/Teuchos_LabeledObject.hpp new file mode 100644 index 0000000000..c1fe7d9c18 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_LabeledObject.hpp @@ -0,0 +1,73 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_LABELED_OBJECT_HPP +#define TEUCHOS_LABELED_OBJECT_HPP + +#include "Teuchos_ConfigDefs.hpp" + + +namespace Teuchos { + + +/** \brief Base class for objects that contain a std::string label. + * + * The object label std::string objectLabel set in + * setObjectLabel() should be a simple one-line label given to an + * object to differentiate it from all other objects. A subclass + * implementation can define a default label in some cases but typically this + * label is designed for end users to set to give the object a name that is + * meaningful to the user. The label should not contain any information about + * the actual type of the object. Adding type information is appropriate in + * the Describable interface, which inherits from this interface. + * + * This base class provides a default implementation for the functions + * setObjectLabel() and getObjectLabel() as well as private + * data to hold the label. Subclasses can override these functions but + * general, there should be no need to do so. + * + * \ingroup teuchos_outputting_grp + */ +class LabeledObject { +public: + /** \brief Construct with an empty label. */ + LabeledObject(); + /** \brief . */ + virtual ~LabeledObject(); + /** \brief Set the object label (see LabeledObject). */ + virtual void setObjectLabel( const std::string &objectLabel ); + /** \brief Get the object label (see LabeledObject). */ + virtual std::string getObjectLabel() const; +private: + std::string objectLabel_; +}; + + +} // namespace Teuchos + + +#endif // TEUCHOS_LABELED_OBJECT_HPP diff --git a/fastlib/trilinos/include/Teuchos_Libxml2HandlerAdapter.hpp b/fastlib/trilinos/include/Teuchos_Libxml2HandlerAdapter.hpp new file mode 100644 index 0000000000..f22e679943 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Libxml2HandlerAdapter.hpp @@ -0,0 +1,64 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_LIBXML2HANDLERADAPTER_H +#define TEUCHOS_LIBXML2HANDLERADAPTER_H + +/*! \file Teuchos_Libxml2HandlerAdapter.hpp + \brief libxml2 adapter for the TreeBuildingXMLHandler +*/ + +#include "Teuchos_ConfigDefs.hpp" + +#ifdef HAVE_TEUCHOS_LIBXML2 +#include "Teuchos_TreeBuildingXMLHandler.hpp" +#include "Teuchos_RCP.hpp" + +#include + +extern "C" +{ + /** \ingroup libXML2 callback for start of an XML element. */ + void xmlSAX2StartElement(void* context, + const xmlChar* name, + const xmlChar** attr); + + /** \ingroup libXML2 callback for end of an XML element. */ + void xmlSAX2EndElement(void* context, + const xmlChar* name); + + /** \ingroup libXML2 callback for character data. */ + void xmlSAX2Characters(void* context, + const xmlChar* s, + int len); +}; + +#endif + + +#endif diff --git a/fastlib/trilinos/include/Teuchos_MPIComm.hpp b/fastlib/trilinos/include/Teuchos_MPIComm.hpp new file mode 100644 index 0000000000..17121503d9 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_MPIComm.hpp @@ -0,0 +1,174 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_MPICOMM_H +#define TEUCHOS_MPICOMM_H + +/*! \file Teuchos_MPIComm.hpp + \brief Object representation of a MPI communicator +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_MPISession.hpp" +#include "Teuchos_RCP.hpp" + + + +namespace Teuchos +{ + /** + * \brief Object representation of an MPI communicator. + * + * At present, groups are not implemented so the only communicator + * is MPI_COMM_WORLD. + */ + class MPIComm + { + public: + + //! Empty constructor builds an object for MPI_COMM_WORLD + MPIComm(); + +#ifdef HAVE_MPI + //! Construct a MPIComm for a given MPI communicator + MPIComm(MPI_Comm comm); +#endif + + //! Get an object representing MPI_COMM_WORLD + static MPIComm& world(); + + //! Return process rank + int getRank() const {return myRank_;} + + //! Return number of processors in the communicator + int getNProc() const {return nProc_;} + + //! Synchronize all the processors in the communicator + void synchronize() const ; + + //! @name Collective communications + //@{ + + //! All-to-all gather-scatter + void allToAll(void* sendBuf, int sendCount, int sendType, + void* recvBuf, int recvCount, int recvType) const ; + + //! Variable-length gather-scatter + void allToAllv(void* sendBuf, int* sendCount, int* sendDisplacements, + int sendType, + void* recvBuf, int* recvCount, + int* recvDisplacements, + int recvType) const ; + + //! Do a collective operation, scattering the results to all processors + void allReduce(void* input, void* result, int inputCount, int type, + int op) const ; + + + //! Gather to root + void gather(void* sendBuf, int sendCount, int sendType, + void* recvBuf, int recvCount, int recvType, + int root) const ; + + //! Gather variable-sized arrays to root + void gatherv(void* sendBuf, int sendCount, int sendType, + void* recvBuf, int* recvCount, int* displacements, + int recvType, int root) const ; + + //! Gather to all processors + void allGather(void* sendBuf, int sendCount, int sendType, + void* recvBuf, int recvCount, int recvType) const ; + + //! Variable-length gather to all processors + void allGatherv(void* sendBuf, int sendCount, int sendType, + void* recvBuf, int* recvCount, int* recvDisplacements, + int recvType) const ; + + //! Broadcast + void bcast(void* msg, int length, int type, int src) const ; + + //@} + +#ifdef HAVE_MPI + //! Get the MPI_Comm communicator handle + MPI_Comm getComm() const {return comm_;} +#endif + + //! @name Data types + //@{ + //! Integer data type + const static int INT; + //! Float data type + const static int FLOAT; + //! Double data type + const static int DOUBLE; + //! Character data type + const static int CHAR; + //@} + + //! @name Operations + //@{ + //! Summation operation + const static int SUM; + //! Minimize operation + const static int MIN; + //! Maximize operation + const static int MAX; + //! Dot-product (Multiplication) operation + const static int PROD; + //@} + + // errCheck() checks the return value of an MPI call and throws + // a ParallelException upon failure. + static void errCheck(int errCode, const std::string& methodName); + +#ifdef HAVE_MPI + //! Converts a PMachine data type code to a MPI_Datatype + static MPI_Datatype getDataType(int type); + + //! Converts a PMachine operator code to a MPI_Op operator code. + static MPI_Op getOp(int op); +#endif + private: +#ifdef HAVE_MPI + MPI_Comm comm_; +#endif + + int nProc_; + int myRank_; + + /** common initialization function, called by all ctors */ + void init(); + + /** Indicate whether MPI is currently running */ + int mpiIsRunning() const ; + }; +} +#endif + diff --git a/fastlib/trilinos/include/Teuchos_MPIContainerComm.hpp b/fastlib/trilinos/include/Teuchos_MPIContainerComm.hpp new file mode 100644 index 0000000000..75971d9904 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_MPIContainerComm.hpp @@ -0,0 +1,711 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_MPICONTAINERCOMM_H +#define TEUCHOS_MPICONTAINERCOMM_H + +/*! \file Teuchos_MPIContainerComm.hpp + \brief Object representation of an MPI communicator for templated containers +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_MPIComm.hpp" +#include "Teuchos_MPITraits.hpp" + +namespace Teuchos +{ + /** \ingroup MPI + * \brief Object representation of an MPI communicator for templated containers + * \note Template specialization exists for std::string. + * @author Kevin Long + */ + + template class MPIContainerComm + { + public: + + //! Broadcast a single object + static void bcast(T& x, int src, const MPIComm& comm); + + //! Broadcast an array of objects + static void bcast(Array& x, int src, const MPIComm& comm); + + //! Broadcast an array of arrays + static void bcast(Array >& x, + int src, const MPIComm& comm); + + //! Gather to all processors + static void allGather(const T& outgoing, + Array& incoming, + const MPIComm& comm); + + //! All-to-all scatter/gather for an array of objects + static void allToAll(const Array& outgoing, + Array >& incoming, + const MPIComm& comm); + + //! All-to-all scatter/gather for an array of arrays + static void allToAll(const Array >& outgoing, + Array >& incoming, + const MPIComm& comm); + + /** Gatherv: gather arrays of data to the root processor */ + static void gatherv(const Array& outgoing, + Array >& incoming, + int rootRank, + const MPIComm& comm); + + //! Sum local values from all processors with rank < myRank + static void accumulate(const T& localValue, Array& sums, T& total, + const MPIComm& comm); + + private: + //! Build a 1D array and an offset list from a 2D array + static void getBigArray(const Array >& x, + Array& bigArray, + Array& offsets); + + //! Reassemble a 2D array from a 1D array and an offset table + static void getSmallArrays(const Array& bigArray, + const Array& offsets, + Array >& x); + + + }; + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + /** \ingroup MPI + * Specialiaztion of MPIContainerComm to std::string + */ + template <> class MPIContainerComm + { + public: + static void bcast(std::string& x, int src, const MPIComm& comm); + + /** bcast an array of objects */ + static void bcast(Array& x, int src, const MPIComm& comm); + + /** bcast an array of arrays */ + static void bcast(Array >& x, + int src, const MPIComm& comm); + + /** AllGather: each process sends a single object to all other procs */ + static void allGather(const std::string& outgoing, + Array& incoming, + const MPIComm& comm); + + /** Gatherv: gather arrays of strings to the root processor */ + static void gatherv(const Array& outgoing, + Array >& incoming, + int rootRank, + const MPIComm& comm); + + /** get a single big array of characters from an array of strings, + * packing the structural description into the header of the packed + * array as follows: + * \code + * [numStrings, offset0, offset1, ..., offsetN, char data] + * \endcode + */ + static void pack(const Array& x, + Array& packed); + + /** recover an array of strings from a single big array and + * and offset table */ + static void unpack(const Array& packed, + Array& x); + private: + /** get a single big array of characters from an array of strings */ + static void getBigArray(const Array& x, + Array& bigArray, + Array& offsets); + + /** recover an array of strings from a single big array and + * and offset table */ + static void getStrings(const Array& bigArray, + const Array& offsets, + Array& x); + }; + +#endif // DOXYGEN_SHOULD_SKIP_THIS + + /* --------- generic functions for primitives ------------------- */ + + template inline void MPIContainerComm::bcast(T& x, int src, + const MPIComm& comm) + { + comm.bcast((void*)&x, 1, MPITraits::type(), src); + } + + + /* ----------- generic functions for arrays of primitives ----------- */ + + template + inline void MPIContainerComm::bcast(Array& x, int src, const MPIComm& comm) + { + int len = x.length(); + MPIContainerComm::bcast(len, src, comm); + + if (comm.getRank() != src) + { + x.resize(len); + } + if (len==0) return; + + /* then broadcast the contents */ + comm.bcast((void*) &(x[0]), (int) len, + MPITraits::type(), src); + } + + + + /* ---------- generic function for arrays of arrays ----------- */ + + template + inline void MPIContainerComm::bcast(Array >& x, int src, const MPIComm& comm) + { + Array bigArray; + Array offsets; + + if (src==comm.getRank()) + { + getBigArray(x, bigArray, offsets); + } + + bcast(bigArray, src, comm); + MPIContainerComm::bcast(offsets, src, comm); + + if (src != comm.getRank()) + { + getSmallArrays(bigArray, offsets, x); + } + } + + /* ---------- generic gather and scatter ------------------------ */ + + template inline + void MPIContainerComm::allToAll(const Array& outgoing, + Array >& incoming, + const MPIComm& comm) + { + int numProcs = comm.getNProc(); + + // catch degenerate case + if (numProcs==1) + { + incoming.resize(1); + incoming[0] = outgoing; + return; + } + + Array sb(numProcs * outgoing.length()); + Array rb(numProcs * outgoing.length()); + + T* sendBuf = new T[numProcs * outgoing.length()]; + TEST_FOR_EXCEPTION(sendBuf==0, + std::runtime_error, "Comm::allToAll failed to allocate sendBuf"); + + T* recvBuf = new T[numProcs * outgoing.length()]; + TEST_FOR_EXCEPTION(recvBuf==0, + std::runtime_error, "Comm::allToAll failed to allocate recvBuf"); + + int i; + for (i=0; i::type(), + recvBuf, outgoing.length(), MPITraits::type()); + + incoming.resize(numProcs); + + for (i=0; i inline + void MPIContainerComm::allToAll(const Array >& outgoing, + Array >& incoming, const MPIComm& comm) + { + int numProcs = comm.getNProc(); + + // catch degenerate case + if (numProcs==1) + { + incoming = outgoing; + return; + } + + int* sendMesgLength = new int[numProcs]; + TEST_FOR_EXCEPTION(sendMesgLength==0, + std::runtime_error, "failed to allocate sendMesgLength"); + int* recvMesgLength = new int[numProcs]; + TEST_FOR_EXCEPTION(recvMesgLength==0, + std::runtime_error, "failed to allocate recvMesgLength"); + + int p = 0; + for (p=0; p0) + { + sendDisp[p] = sendDisp[p-1] + sendMesgLength[p-1]; + recvDisp[p] = recvDisp[p-1] + recvMesgLength[p-1]; + } + } + + comm.allToAllv(sendBuf, sendMesgLength, + sendDisp, MPITraits::type(), + recvBuf, recvMesgLength, + recvDisp, MPITraits::type()); + + incoming.resize(numProcs); + for (p=0; p inline + void MPIContainerComm::allGather(const T& outgoing, Array& incoming, + const MPIComm& comm) + { + int nProc = comm.getNProc(); + incoming.resize(nProc); + + if (nProc==1) + { + incoming[0] = outgoing; + } + else + { + comm.allGather((void*) &outgoing, 1, MPITraits::type(), + (void*) &(incoming[0]), 1, MPITraits::type()); + } + } + + template inline + void MPIContainerComm::accumulate(const T& localValue, Array& sums, + T& total, + const MPIComm& comm) + { + Array contributions; + allGather(localValue, contributions, comm); + sums.resize(comm.getNProc()); + sums[0] = 0; + total = contributions[0]; + + for (int i=0; i inline + void MPIContainerComm::getBigArray(const Array >& x, Array& bigArray, + Array& offsets) + { + offsets.resize(x.length()+1); + int totalLength = 0; + + for (int i=0; i inline + void MPIContainerComm::getSmallArrays(const Array& bigArray, + const Array& offsets, + Array >& x) + { + x.resize(offsets.length()-1); + for (int i=0; i::bcast(std::string& x, + int src, const MPIComm& comm) + { + int len = x.length(); + MPIContainerComm::bcast(len, src, comm); + + x.resize(len); + comm.bcast((void*)&(x[0]), len, MPITraits::type(), src); + } + + + inline void MPIContainerComm::bcast(Array& x, int src, + const MPIComm& comm) + { + /* begin by packing all the data into a big char array. This will + * take a little time, but will be cheaper than multiple MPI calls */ + Array bigArray; + Array offsets; + if (comm.getRank()==src) + { + getBigArray(x, bigArray, offsets); + } + + /* now broadcast the big array and the offsets */ + MPIContainerComm::bcast(bigArray, src, comm); + MPIContainerComm::bcast(offsets, src, comm); + + /* finally, reassemble the array of strings */ + if (comm.getRank() != src) + { + getStrings(bigArray, offsets, x); + } + } + + inline void MPIContainerComm::bcast(Array >& x, + int src, const MPIComm& comm) + { + int len = x.length(); + MPIContainerComm::bcast(len, src, comm); + + x.resize(len); + for (int i=0; i::bcast(x[i], src, comm); + } + } + + + inline void MPIContainerComm::allGather(const std::string& outgoing, + Array& incoming, + const MPIComm& comm) + { + int nProc = comm.getNProc(); + + int sendCount = outgoing.length(); + + incoming.resize(nProc); + + int* recvCounts = new int[nProc]; + int* recvDisplacements = new int[nProc]; + + /* share lengths with all procs */ + comm.allGather((void*) &sendCount, 1, MPIComm::INT, + (void*) recvCounts, 1, MPIComm::INT); + + + int recvSize = 0; + recvDisplacements[0] = 0; + for (int i=0; i::gatherv(const Array& outgoing, + Array >& incoming, + int root, + const MPIComm& comm) + { + int nProc = comm.getNProc(); + + Array packedLocalArray; + pack(outgoing, packedLocalArray); + + int sendCount = packedLocalArray.size(); + + /* gather the message sizes from all procs */ + Array recvCounts(nProc); + Array recvDisplacements(nProc); + + comm.gather((void*) &sendCount, 1, MPIComm::INT, + (void*) &(recvCounts[0]), 1, MPIComm::INT, root); + + /* compute the displacements */ + int recvSize = 0; + if (root == comm.getRank()) + { + recvDisplacements[0] = 0; + for (int i=0; i recvBuf(std::max(1,recvSize)); + + + void* sendBuf = (void*) &(packedLocalArray[0]); + void* inBuf = (void*) &(recvBuf[0]); + int* inCounts = inCounts = &(recvCounts[0]); + int* inDisps = inDisps = &(recvDisplacements[0]); + + /* gather the packed data */ + comm.gatherv( sendBuf, sendCount, MPIComm::CHAR, + inBuf, inCounts, inDisps, + MPIComm::CHAR, root); + + /* on the root, unpack the data */ + if (comm.getRank()==root) + { + incoming.resize(nProc); + for (int j=0; j tmp(recvCounts[j]+1); + std::memcpy(&(tmp[0]), start, recvCounts[j]); + tmp[recvCounts[j]] = '\0'; + unpack(tmp, incoming[j]); + } + } + + + } + + + inline void MPIContainerComm::getBigArray(const Array& x, + Array& bigArray, + Array& offsets) + { + offsets.resize(x.length()+1); + int totalLength = 0; + + for (int i=0; i::pack(const Array& x, + Array& bigArray) + { + Array offsets(x.size()+1); + int headerSize = (x.size()+2) * sizeof(int); + + int totalLength = headerSize; + + for (int i=0; i( &(bigArray[0]) ); + header[0] = x.size(); + for (unsigned int i=0; i<=x.size(); i++) + { + header[i+1] = offsets[i]; + } + + for (int i=0; i::unpack(const Array& packed, + Array& x) + { + const int* header = reinterpret_cast( &(packed[0]) ); + + x.resize(header[0]); + Array offsets(x.size()+1); + for (unsigned int i=0; i<=x.size(); i++) offsets[i] = header[i+1]; + + for (unsigned int i=0; i::getStrings(const Array& bigArray, + const Array& offsets, + Array& x) + { + x.resize(offsets.length()-1); + for (int i=0; ichar
    , + int, float, and double. + */ + template class MPITraits + { + public: + /** \brief Return the MPI data type of the template argument */ + static int type(); + }; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + /** \ingroup MPI + * Binds MPI_INT to int + */ + template <> class MPITraits + { + public: + /** return the MPI data type of the template argument */ + static int type() {return MPIComm::INT;} + }; + + /** \ingroup MPI + * Binds MPI_FLOAT to float + */ + template <> class MPITraits + { + public: + /** return the MPI data type of the template argument */ + static int type() {return MPIComm::FLOAT;} + }; + + /** \ingroup MPI + * Binds MPI_DOUBLE to double + */ + template <> class MPITraits + { + public: + /** return the MPI data type of the template argument */ + static int type() {return MPIComm::DOUBLE;} + }; + + /** \ingroup MPI + * Binds MPI_CHAR to char + */ + template <> class MPITraits + { + public: + /** return the MPI data type of the template argument */ + static int type() {return MPIComm::CHAR;} + }; + +#endif //DOXYGEN_SHOULD_SKIP_THIS + +} // namespace Teuchos + +#endif diff --git a/fastlib/trilinos/include/Teuchos_Object.hpp b/fastlib/trilinos/include/Teuchos_Object.hpp new file mode 100644 index 0000000000..ff36b7b705 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Object.hpp @@ -0,0 +1,179 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef _TEUCHOS_OBJECT_HPP_ +#define _TEUCHOS_OBJECT_HPP_ + +/*! \file Teuchos_Object.hpp + \brief The base Teuchos object. +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_DataAccess.hpp" + +/*! \class Teuchos::Object + \brief The base Teuchos class. + + The Object class provides capabilities common to all Teuchos objects, + such as a label that identifies an object instance, constant definitions, + enum types. +*/ + +namespace Teuchos +{ + +class Object +{ + public: + //! @name Constructors/Destructor. + //@{ + //! Default Constructor. + /*! Object is the primary base class in Teuchos. All Teuchos class + are derived from it, directly or indirectly. This class is seldom + used explictly. + */ + Object(int tracebackModeIn = -1); + + //! Labeling Constructor. + /*! Creates an Object with the given label. + */ + Object(const char* label, int tracebackModeIn = -1); + + //! Copy Constructor. + /*! Makes an exact copy of an existing Object instance. + */ + Object(const Object& obj); + + //! Destructor. + /*! Completely deletes an Object object. + */ + virtual ~Object(); + + //@} + + //! @name Set methods. + //@{ + + //! Define object label using a character std::string. + /*! Defines the label used to describe \c this object. + */ + virtual void setLabel(const char* label); + + //! Set the value of the Object error traceback report mode. + /*! Sets the integer error traceback behavior. + TracebackMode controls whether or not traceback information is printed when run time + integer errors are detected: + + <= 0 - No information report + + = 1 - Fatal (negative) values are reported + + >= 2 - All values (except zero) reported. + + \note Default is set to -1 when object is constructed. + */ + static void setTracebackMode(int tracebackModeValue); + + //@} + + //! @name Accessor methods. + //@{ + + //! Access the object label. + /*! Returns the std::string used to define \e this object. + */ + virtual char* label() const; + + //! Get the value of the Object error traceback report mode. + static int getTracebackMode(); + + //@} + + //! @name I/O method. + //@{ + + //! Print method for placing the object in an output stream + virtual void print(std::ostream& os) const; + //@} + + //! @name Error reporting method. + //@{ + + //! Method for reporting errors with Teuchos objects. + virtual int reportError(const std::string message, int errorCode) const + { + // NOTE: We are extracting a C-style std::string from Message because + // the SGI compiler does not have a real std::string class with + // the << operator. Some day we should get rid of ".c_str()" + if ( (tracebackMode==1) && (errorCode < 0) ) + { // Report fatal error + std::cerr << std::endl << "Error in Teuchos Object with label: " << label_ << std::endl + << "Teuchos Error: " << message.c_str() << " Error Code: " << errorCode << std::endl; + return(errorCode); + } + if ( (tracebackMode==2) && (errorCode != 0 ) ) + { + std::cerr << std::endl << "Error in Teuchos Object with label: " << label_ << std::endl + << "Teuchos Error: " << message.c_str() << " Error Code: " << errorCode << std::endl; + return(errorCode); + } + return(errorCode); + } + + //@} + + static int tracebackMode; + + protected: + + private: + + char* label_; + +}; // class Object + +/*! \relates Object + Output stream operator for handling the printing of Object. +*/ +inline std::ostream& operator<<(std::ostream& os, const Teuchos::Object& Obj) +{ + os << Obj.label() << std::endl; + Obj.print(os); + + return os; +} + +} // namespace Teuchos + +// #include "Teuchos_Object.cpp" + + +#endif /* _TEUCHOS_OBJECT_HPP_ */ diff --git a/fastlib/trilinos/include/Teuchos_OpaqueWrapper.hpp b/fastlib/trilinos/include/Teuchos_OpaqueWrapper.hpp new file mode 100644 index 0000000000..21278bbcce --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_OpaqueWrapper.hpp @@ -0,0 +1,195 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_OPAQUE_WRAPPER_HPP +#define TEUCHOS_OPAQUE_WRAPPER_HPP + +#include "Teuchos_RCP.hpp" + +//#define TEUCHOS_OPAQUE_WRAPPER_ANNOUNCE_FREE + +#ifdef TEUCHOS_OPAQUE_WRAPPER_ANNOUNCE_FREE +# include "Teuchos_VerboseObject.hpp" +#endif // TEUCHOS_OPAQUE_WRAPPER_ANNOUNCE_FREE + +namespace Teuchos { + +/** \brief Base class for wrapped opaque objects. + * + * This base class allows opaque objects to be wrapped by a real object that + * you can then take an address off. This is needed in order to wrap an + * opaque object in a RCP for example. + * + * For example, MPI uses the opaque object idiom for handling things like + * MPI_Comm, and MPI_Op. Some implementations implement these opaque object + * handles and just integers. This causes many problems with used with the + * RCP (just try wrapping an MPI_Comm object directly in a RCP + * and see what happens yourself and see what happens). + * + * For example, to wrap MPI_COMM_WORLD in a RCP, you would do + * opaqueWrapper(MPI_COMM_WORLD) and that is it. + * + * Consider what would happen if you tried to directly wrap the MPI_Comm + * MPI_COMM_WORLD in a RCP. On some implementations like MPICH, + * MPI_Comm is just a typedef to an integer and MPI_COMM_WORLD is just a define + * to a literal interger. In this case, the expression + * rcp(&MPI_COMM_WORLD) would not even compile (try this on your + * version of MPICH). To make this compile, we might try something like: + + \code + + Teuchos::RCP getMpiCommPtr() + { + MPI_Comm comm = MPI_COMM_WORLD; + return Teuchos::rcp(&comm,false); + } + + \endcode + + * Of course the above code would result in a disaster when the stack variable + * comm, which is just an integer in MPICH, was destroyed and + * reclaimed. The RCP returned from getMpiCommPtr() would + * contain a raw pointer an int object that was now being used for + * something else and would no longer have the integer value of a valid + * MPI_Comm object. + * + * The following implementation would most likely work but is pretty ugly: + + \code + + Teuchos::RCP getMpiCommPtr() + { + MPI_Comm *comm = new MPI_Comm(MPI_COMM_WORLD); + return Teuchos::rcp(&comm); + } + + \endcode + + * The above implementation of getMPiCommPtr() would work with MPICH but it is + * unclear how this would work with other implementations of MPI (but it + * should work for these also). However, this is pretty ugly to do. + * + * There are other issues that crop up also when you play these types of games. + * + * Therefore, just use opaqueWrapper() create wrap opaque objects in + * RCP objects and be sure that this will go smoothly. + * + * \ingroup teuchos_mem_mng_grp + */ +template +class OpaqueWrapper { +public: + /** \brief . */ + OpaqueWrapper( Opaque opaque ) + : opaque_(opaque) + {} + /** \brief . */ + operator Opaque () const + { return opaque_; } + /** \brief . */ + Opaque operator()() const + { return opaque_; } +protected: + Opaque opaque_; // Bad in general but ... +private: + OpaqueWrapper(); // Not defined + OpaqueWrapper(const OpaqueWrapper&); // Not defined + OpaqueWrapper& operator=(const OpaqueWrapper&); // Not defined +}; + +/** \brief Subclass for wrapped opaque objects with a free function. + * + * This subclass allows a client to easily wrap any opaque object that needs a + * function to free it. This function (or function object) must be callable + * as: + + \code + opaqueFree(&opaque); + \endcode + + * Again, this is typical for the opaque objects implemented in MPI for + * instance. For example, in order to delete an MPI_Comm object created by + * the user (not MPI_COMM_WORLD), you must call the function MPI_Comm_free(). + * + * \relates OpaqueWrapper + */ +template +class OpaqueWrapperWithFree : public OpaqueWrapper { +public: + OpaqueWrapperWithFree( Opaque opaque, OpaqueFree opaqueFree ) + : OpaqueWrapper(opaque), opaqueFree_(opaqueFree) + {} + ~OpaqueWrapperWithFree() + { + if(opaqueFree_) { +#ifdef TEUCHOS_OPAQUE_WRAPPER_ANNOUNCE_FREE + Teuchos::RCP + out = Teuchos::VerboseObjectBase::getDefaultOStream(); + Teuchos::OSTab tab(out); + *out << "\nOpaqueWrapperWithFree::~OpaqueWrapperWithFree(): Freeing opaque object" + << " of type " << TypeNameTraits::name() << "!\n"; +#endif // TEUCHOS_OPAQUE_WRAPPER_ANNOUNCE_FREE + opaqueFree_(&this->opaque_); + } + } +private: + OpaqueFree opaqueFree_; + OpaqueWrapperWithFree(); // Not defined + OpaqueWrapperWithFree(const OpaqueWrapperWithFree&); // Not defined + OpaqueWrapperWithFree& operator=(const OpaqueWrapperWithFree&); // Not defined +}; + +/** \brief Helper function created a new OpaqueWrapper object without + * a free function. + * + * \relates OpaqueWrapper + */ +template +inline +RCP > +opaqueWrapper( Opaque opaque) +{ + return rcp(new OpaqueWrapper(opaque)); +} + +/** \brief Helper function created a new OpaqueWrapper object with a + * free function. + * + * \relates OpaqueWrapper + */ +template +inline +RCP > +opaqueWrapper( Opaque opaque, OpaqueFree opaqueFree) +{ + return rcp(new OpaqueWrapperWithFree(opaque,opaqueFree)); +} + +} // namespace Teuchos + +#endif // TEUCHOS_OPAQUE_WRAPPER_HPP diff --git a/fastlib/trilinos/include/Teuchos_OrdinalTraits.hpp b/fastlib/trilinos/include/Teuchos_OrdinalTraits.hpp new file mode 100644 index 0000000000..a74ae5d6e9 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_OrdinalTraits.hpp @@ -0,0 +1,124 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef _TEUCHOS_ORDINALTRAITS_HPP_ +#define _TEUCHOS_ORDINALTRAITS_HPP_ + +/*! \file Teuchos_OrdinalTraits.hpp + \brief Defines basic traits for the ordinal field type +*/ + +#include "Teuchos_ConfigDefs.hpp" + +/*! \struct Teuchos::OrdinalTraits + \brief This structure defines some basic traits for the ordinal field type. + + Ordinal traits are an essential part of templated codes. This structure offers + the basic traits of the templated ordinal type, like defining zero and one. + + For the general type, or default implementation, an aborting function + is defined which should restrict implementations from using ordinal traits other than + the defined specializations. + + \note The defined specializations for OrdinalTraits are: \c int and \c long \c int. +*/ + +/* This is the default structure used by OrdinalTraits to produce a compile time + error when the specialization does not exist for type T. +*/ +namespace Teuchos { + +template +struct UndefinedOrdinalTraits +{ + //! This function should not compile if there is an attempt to instantiate! + static inline T notDefined() { return T::this_type_is_missing_a_specialization(); } +}; + +template +struct OrdinalTraits { + + //! Allows testing to see if ordinal traits machine parameters are defined. + static const bool hasMachineParameters = false; + + //! Returns representation of zero for this ordinal type. + static inline T zero() { return UndefinedOrdinalTraits::notDefined(); } + + //! Returns representation of one for this ordinal type. + static inline T one() { return UndefinedOrdinalTraits::notDefined(); } + + //! Returns name of this ordinal type. + static inline std::string name() { return UndefinedOrdinalTraits::notDefined(); } +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +template<> +struct OrdinalTraits { + + static const bool hasMachineParameters = false; + static inline char zero() {return(0);} + static inline char one() {return(1);} + static inline std::string name() {return("char");} +}; + +template<> +struct OrdinalTraits { + + static const bool hasMachineParameters = false; + static inline short int zero() {return(0);} + static inline short int one() {return(1);} + static inline std::string name() {return("short int");} +}; + +template<> +struct OrdinalTraits { + + static const bool hasMachineParameters = false; + static inline int zero() {return(0);} + static inline int one() {return(1);} + static inline std::string name() {return("int");} +}; + +template<> +struct OrdinalTraits { + + static const bool hasMachineParameters = false; + static inline long int zero() {return(static_cast(0));} + static inline long int one() {return(static_cast(1));} + static inline std::string name() {return("long int");} +}; + +#endif + +} // namespace Teuchos + +#endif // _TEUCHOS_ORDINALTRAITS_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_ParameterEntry.hpp b/fastlib/trilinos/include/Teuchos_ParameterEntry.hpp new file mode 100644 index 0000000000..b4c26398f7 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterEntry.hpp @@ -0,0 +1,352 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +#ifndef TEUCHOS_PARAMETER_ENTRY_H +#define TEUCHOS_PARAMETER_ENTRY_H + +/*! \file Teuchos_ParameterEntry.hpp + \brief Object held as the "value" in the Teuchos::ParameterList std::map. +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_any.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_ParameterEntryValidator.hpp" + +namespace Teuchos { + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +class ParameterList; // another parameter type (forward declaration) +#endif + +/*! \brief This object is held as the "value" in the Teuchos::ParameterList std::map. + + This structure holds a \c Teuchos::any value and information on the status of this + parameter (isUsed, isDefault, etc.). The type of parameter is chosen through the + templated Set/Get methods. +*/ +class ParameterEntry { +public: + + //! @name Constructors/Destructor + //@{ + + //! Default Constructor + ParameterEntry(); + + //! Copy constructor + ParameterEntry(const ParameterEntry& source); + + //! Templated constructor + template + explicit ParameterEntry( + T value, bool isDefault = false, bool isList = false, + const std::string &docString = "", + RCP const& validator = null + ); + + //! Destructor + ~ParameterEntry(); + + //@} + + //! @name Set Methods + //@{ + + //! Replace the current parameter entry with \c source. + ParameterEntry& operator=(const ParameterEntry& source); + + /*! \brief Templated set method that uses the input value type to determine the type of parameter. + + \note
      +
    • Invalidates any previous values stored by this object although it doesn't necessarily erase them. +
    • Resets 'isUsed' functionality. +
    + */ + template + void setValue( + T value, bool isDefault = false, + const std::string &docString = "", + RCP const& validator = null + ); + + /*! \brief Set the value as an any object. + * + * This wipes all other data including documentation strings. + * + * Warning! Do not use function ths to set a sublist! + */ + void setAnyValue( + const any &value, bool isDefault = false + ); + + /*! \brief Set the validator. */ + void setValidator( + RCP const& validator + ); + + /*! \brief Set the documentation std::string. */ + void setDocString(const std::string &docString); + + //! Create a parameter entry that is an empty list. + ParameterList& setList( + bool isDefault = false, + const std::string &docString = "" + ); + + //@} + + //! @name Get Methods + //@{ + + /*! \brief Templated get method that uses the input pointer type to determine the type of parameter to return. + + \note This method will cast the value to the type requested. If that type is incorrect, + an std::exception will be thrown by the any_cast. + */ + template + T& getValue(T *ptr) const; + + /*! \brief Direct access to the Teuchos::any data value underlying this + * object. The bool argument \c activeQry (default: true) indicates that the + * call to getAny() will set the isUsed() value of the ParameterEntry to true. + */ + any& getAny(bool activeQry = true); + + /*! \brief Constant direct access to the Teuchos::any data value underlying this + * object. The bool argument \c activeQry (default: true) indicates that the + * call to getAny() will set the isUsed() value of the ParameterEntry to true. + */ + const any& getAny(bool activeQry = true) const; + + //@} + + //! @name Attribute/Query Methods + //@{ + + //! Return whether or not the value has been used; i.e., whether or not the value has been retrieved via a get function. + bool isUsed() const; + + //! Return whether or not the value itself is a list. + bool isList() const; + + //! Test the type of the data being contained. + template + bool isType() const; + + //! Indicate whether this entry takes on the default value. + bool isDefault() const; + + //! Return the (optional) documentation std::string + std::string docString() const; + + //! Return the (optional) validator object + RCP validator() const; + + //@} + + //! @name I/O Methods + + /*! \brief Output a non-list parameter to the given output stream. + + The parameter is followed by "[default]" if it is the default value given through a + Set method. Otherwise, if the parameter was unused (not accessed through a Get method), + it will be followed by "[unused]". This function is called by the "std::ostream& operator<<". + */ + std::ostream& leftshift(std::ostream& os, bool printFlags = true) const; + + //@} + +private: + + //! Reset the entry + void reset(); + + //! Templated Datatype + any val_; + + //! Has this parameter been accessed by a "get" function? + mutable bool isUsed_; + + //! Was this parameter a default value assigned by a "get" function? + mutable bool isDefault_; + + //! Optional documentation field + std::string docString_; + + //! Optional validator object + RCP validator_; + +}; + +/*! \relates ParameterEntry + \brief A templated helper function for returning the value of type \c T held in the ParameterEntry object, + where the type \c T can be specified in the call. This is an easier way to call the getValue method + in the ParameterEntry class, since the user does not have to pass in a pointer of type \c T. +*/ +template +inline T& getValue( const ParameterEntry &entry ) +{ + return entry.getValue((T*)NULL); +} + +/*! \relates ParameterEntry + \brief Returns true if two ParameterEntry objects are equal. +*/ +inline bool operator==(const ParameterEntry& e1, const ParameterEntry& e2) +{ + return ( + e1.getAny() == e2.getAny() + && e1.isList()== e2.isList() + && e1.isUsed() == e2.isUsed() + && e1.isDefault() == e2.isDefault() + ); +} + +/*! \relates ParameterEntry + \brief Returns true if two ParameterEntry objects are not equal. +*/ +inline bool operator!=(const ParameterEntry& e1, const ParameterEntry& e2) +{ + return !( e1 == e2 ); +} + +/*! \relates ParameterEntry + \brief Output stream operator for handling the printing of parameter entries. +*/ +inline std::ostream& operator<<(std::ostream& os, const ParameterEntry& e) +{ + return e.leftshift(os); +} + +// /////////////////////////////////////////// +// Inline and Template Function Definitions + +// Constructor/Destructor + +template +inline +ParameterEntry::ParameterEntry( + T value, bool isDefault, bool isList + ,const std::string &docString + ,RCP const& validator + ) + : val_(value), + isUsed_(false), + isDefault_(isDefault), + docString_(docString), + validator_(validator) +{} + +inline +ParameterEntry::~ParameterEntry() +{} + +// Set Methods + +template +inline +void ParameterEntry::setValue( + T value, bool isDefault, const std::string &docString + ,RCP const& validator + ) +{ + val_ = value; + isDefault_ = isDefault; + if(docString.length()) + docString_ = docString; + if(validator.get()) + validator_ = validator; +} + +// Get Methods + +template +inline +T& ParameterEntry::getValue(T *ptr) const +{ + isUsed_ = true; + return const_cast(Teuchos::any_cast( val_ )); +} + +inline +any& ParameterEntry::getAny(bool activeQry) +{ + if (activeQry == true) { + isUsed_ = true; + } + return val_; +} + +inline +const any& ParameterEntry::getAny(bool activeQry) const +{ + if (activeQry == true) { + isUsed_ = true; + } + return val_; +} + +// Attribute Methods + +inline +bool ParameterEntry::isUsed() const +{ return isUsed_; } + +template +inline +bool ParameterEntry::isType() const +{ + bool match = ( val_.type() == typeid(T) ); +#ifdef HAVE_SHARED + // For shared libraries, the above may resolve as false because one + // of the types is not fully qualified. The following check will + // compensate for that. + if ( !match ) + match = ( strcmp(val_.type().name(), typeid(T).name()) == 0 ); +#endif + return match; +} + +inline +bool ParameterEntry::isDefault() const +{ return isDefault_; } + +inline +std::string ParameterEntry::docString() const +{ return docString_; } + +inline +RCP +ParameterEntry::validator() const +{ return validator_; } + +} // namespace Teuchos + +#endif diff --git a/fastlib/trilinos/include/Teuchos_ParameterEntryValidator.hpp b/fastlib/trilinos/include/Teuchos_ParameterEntryValidator.hpp new file mode 100644 index 0000000000..61d91ff239 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterEntryValidator.hpp @@ -0,0 +1,129 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +#ifndef TEUCHOS_PARAMETER_ENTRY_VALIDATOR_H +#define TEUCHOS_PARAMETER_ENTRY_VALIDATOR_H + +#include "Teuchos_RCP.hpp" +#include "Teuchos_Array.hpp" + +namespace Teuchos { + + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +class ParameterEntry; +#endif + + +/** \brief Abstract interface for an object that can validate a + * ParameterEntry's value. + * + * Not only can a validator validate and entry but it can also help to set + * and/or adjust the default value. + */ +class ParameterEntryValidator { +public: + + /** \brief . */ + virtual ~ParameterEntryValidator() {} + + /** \brief Print documentation for this parameter. + * + * \param docString + * [in] (Multi-line) documentation std::string. + * \param out + * [out] The std::ostream used for the output + * + * The purpose of this function is to augment what is in docString + * with some description of what valid values this parameter validator will + * accept. + */ + virtual void printDoc( + std::string const& docString + ,std::ostream & out + ) const = 0; + + /** \brief Return an array of strings of valid values if applicable. + * + * If there is no such array of std::string values that makes since, just return + * return.get()==NULL. + * + * The returned strings must not contain any newlines (i.e. no '\n' + * characters) and must be short enough to fit on one line and be readable. + */ + virtual Teuchos::RCP > + validStringValues() const = 0; + + /** \brief Validate a parameter entry value and throw std::exception (with a + * great error message) if validation fails. + * + * \param entry + * [in] The ParameterEntry who's type and value is being validated + * \param paramName + * [in] The name of the ParameterEntry that is used to build error messages. + * \param sublistName + * [in] The name of the ParameterList that paramName exists in + * that is used to build error messages. + */ + virtual void validate( + ParameterEntry const& entry, + std::string const& paramName, + std::string const& sublistName + ) const = 0; + + /** \brief Validate and perhaps modify a parameter entry's value. + * + * \param paramName + * [in] The name of the ParameterEntry that is used to build error messages. + * \param sublistName + * [in] The name of the ParameterList that paramName exists in + * that is used to build error messages. + * \param entry + * [in/out] The ParameterEntry who's type and value is being validated and + * perhaps even changed as a result of calling this function. + * + * The default implementation simply calls this->validate(). + */ + virtual void validateAndModify( + std::string const& paramName, + std::string const& sublistName, + ParameterEntry * entry + ) const + { + TEST_FOR_EXCEPT(0==entry); + this->validate(*entry,paramName,sublistName); + } + +}; + + +} // namespace Teuchos + + +#endif // TEUCHOS_PARAMETER_ENTRY_VALIDATOR_H diff --git a/fastlib/trilinos/include/Teuchos_ParameterList.hpp b/fastlib/trilinos/include/Teuchos_ParameterList.hpp new file mode 100644 index 0000000000..d00b1e40ea --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterList.hpp @@ -0,0 +1,1112 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +#ifndef TEUCHOS_PARAMETER_LIST_H +#define TEUCHOS_PARAMETER_LIST_H + +/*! \file Teuchos_ParameterList.hpp + \brief Templated Parameter List class +*/ + +#include "Teuchos_ParameterListExceptions.hpp" +#include "Teuchos_ParameterEntry.hpp" +#include "Teuchos_TestForException.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_map.hpp" + +/** \example ParameterList/cxx_main.cpp + This is an example of how to use the Teuchos::ParameterList class. +*/ + +namespace Teuchos { + +/** \brief . + * \relates ParameterList + */ +enum EValidateUsed { + VALIDATE_USED_ENABLED /*< \brief Validate that parameters in *this list + set using the default value are present in + the validation list */ + ,VALIDATE_USED_DISABLED /*< \brief Do not validate that parameters in *this list + set using the default value are present in + the validation list */ +}; + +/** \brief . + * \relates ParameterList + */ +enum EValidateDefaults { + VALIDATE_DEFAULTS_ENABLED /*< \brief Validate that parameters in *this list + set using the default value are present in + the validation list */ + ,VALIDATE_DEFAULTS_DISABLED /*< \brief Do not validate that parameters in *this list + set using the default value are present in + the validation list */ +}; + +/*! \brief Templated parameter list. + + Parameters can be added and retreived with the templated "get" and "set" + functions. These parameters can any data type which uses value sementics + (e.g. double, float, int, *double, *float, *int, ...) which includes other + parameter lists, allowing for a hierarchy of parameter lists. These + parameters can also be pointers to vectors or functions. + + \note
      +
    • Use static_cast() when the type is ambiguous. +
    • Both char* and std::string std::map to are stored as strings internally. +
    +*/ +class ParameterList { + + //! Parameter container typedef + typedef Teuchos::map Map; + + //! Parameter container iterator typedef + typedef Map::iterator Iterator; + +public: + + //! @name Public types + //@{ + + //! Parameter container const iterator typedef + typedef Map::const_iterator ConstIterator; + + /** \brief Utility class for setting and passing in print options. */ + class PrintOptions { + public: + PrintOptions() : indent_(0), showTypes_(false), showFlags_(false), showDoc_(false) {} + PrintOptions& indent(int _indent) { indent_ = _indent; return *this; } + PrintOptions& showTypes(bool _showTypes) { showTypes_ = _showTypes; return *this; } + PrintOptions& showFlags(bool _showFlags) { showFlags_ = _showFlags; return *this; } + PrintOptions& showDoc(bool _showDoc) { showDoc_ = _showDoc; return *this; } + PrintOptions& incrIndent(int indents) { indent_ += indents; return *this; } + int indent() const { return indent_; } + bool showTypes() const { return showTypes_; } + bool showFlags() const { return showFlags_; } + bool showDoc() const { return showDoc_; } + PrintOptions copy() const { return PrintOptions(*this); } + private: + int indent_; + bool showTypes_; + bool showFlags_; + bool showDoc_; + }; + + //@} + + //! @name Constructors/Destructor. + //@{ + + //! Constructor + ParameterList(); + + //! Constructor + ParameterList(const std::string &name); + + //! Copy Constructor + ParameterList(const ParameterList& source); + + //! Deconstructor + virtual ~ParameterList(); + + //@} + + //! @name Set Functions + //@{ + + /** \brief Set the name of *this list. + */ + ParameterList& setName( const std::string &name ); + + /** Replace the current parameter list with \c source. + * \note This also replaces the name returned by this->name() + */ + ParameterList& operator=(const ParameterList& source); + + /** Set the parameters in source. + * + * Note, this function will set the parameters and sublists from + * source into *this but will not result in parameters + * being removed from *this. Parameters in *this with the + * same names as those in source will be overwritten. + */ + ParameterList& setParameters(const ParameterList& source); + + /** Set the parameters in source that are not already set in + * *this. + * + * Note, this function will set the parameters and sublists from + * source into *this but will not result in parameters + * being removed from *this or in parameters already set in + * *this being overrided. Parameters in *this with the + * same names as those in source will not be overwritten. + */ + ParameterList& setParametersNotAlreadySet(const ParameterList& source); + + /** Disallow recusive validation when this sublist is used in a valid + * parameter list. + * + * This function should be called when setting a sublist in a valid + * parameter list which is broken off to be passed to another object. + * The other object should validate its own list. + */ + ParameterList& disableRecursiveValidation(); + + /*! \brief Sets different types of parameters. The type depends on the second entry. + + \note
      +
    • Use static_cast() when the type is ambiguous. +
    • Both char* and std::string std::map to are stored as strings internally. +
    • Sets the parameter as "unused". +
    + */ + template + ParameterList& set( + std::string const& name, T const& value, std::string const& docString = "" + ,RCP const& validator = null + ); + + /*! \brief Template specialization for the case when a user sets the parameter with a character + std::string in parenthesis. + */ + ParameterList& set( + std::string const& name, char value[], std::string const& docString = "" + ,RCP const& validator = null + ); + + /*! \brief Template specialization for the case when a user sets the parameter with a character + std::string in parenthesis. + */ + ParameterList& set( + std::string const& name, const char value[], std::string const& docString = "" + ,RCP const& validator = null + ); + + /*! \brief Template specialization for the case when a user sets the parameter with a ParameterList. + */ + ParameterList& set( + std::string const& name, ParameterList const& value, std::string const& docString = "" + ); + + /*! \brief Set a parameter directly as a ParameterEntry. + * \note This is required to preserve the isDefault value when reading back + * from XML. KL 7 August 2004 + */ + ParameterList& setEntry(const std::string& name, const ParameterEntry& entry); + + //@} + + //! @name Get Functions + //@{ + + /*! \brief Retrieves parameter \c name of type \c T from list, if it exists, else the \c def_value is + used to enter a new parameter into the list. + + \note
      +
    • Use the static_cast() when the type is ambiguous. +
    • Both char* and std::string std::map to are stored as strings internally. +
    • Sets the parameter as "used". +
    • Exception is thrown if \c name exists, but is not of type \c T. +
    + */ + template + T& get(const std::string& name, T def_value); + + /*! \brief Template specialization of get, where the nominal value is a character std::string in parenthesis. + Both char* and std::string are stored as strings and return std::string values. + */ + std::string& get(const std::string& name, char def_value[]); + + /*! \brief Template specialization of get, where the nominal value is a character std::string in parenthesis. + Both char* and std::string are stored as strings and return std::string values. + */ + std::string& get(const std::string& name, const char def_value[]); + + /*! \brief Retrieves parameter \c name of type \c T from a list, an + Exceptions::InvalidParameter std::exception is thrown if this + parameter doesn't exist (Exceptions::InvalidParameterName) or is + the wrong type (Exceptions::InvalidParameterName). \note The + syntax for calling this method is: list.template get( "Iters" ) + + */ + template + T& get(const std::string& name); + + /*! \brief Retrieves parameter \c name of type \c T from a constant list, an + Exceptions::InvalidParameter std::exception is thrown if this + parameter doesn't exist (Exceptions::InvalidParameterName) or is + the wrong type (Exceptions::InvalidParameterName). \note The + syntax for calling this method is: list.template get( "Iters" ) + + */ + template + const T& get(const std::string& name) const; + + /*! \brief Retrieves the pointer for parameter \c name of type \c T from a + list. A null pointer is returned if this parameter doesn't exist or is + the wrong type. \note The syntax for calling this method is: + list.template getPtr( "Iters" ) + */ + template + T* getPtr(const std::string& name); + + /*! \brief Retrieves the pointer for parameter \c name of type \c T from a + constant list. A null pointer is returned if this parameter doesn't exist + or is the wrong type. \note The syntax for calling this method is: + list.template getPtr( "Iters" ) + */ + template + const T* getPtr(const std::string& name) const; + + /*! \brief Retrieves an entry with the name name. + * + * Throws Exceptions::InvalidParameterName if this parameter does + * not exist. + */ + ParameterEntry& getEntry(const std::string& name); + + /*! \brief Retrieves a const entry with the name name. + * + * Throws Exceptions::InvalidParameterName if this parameter does + * not exist. + */ + const ParameterEntry& getEntry(const std::string& name) const; + + /*! \brief Retrieves the pointer for an entry with the name name if + * it exists. */ + ParameterEntry* getEntryPtr(const std::string& name); + + /*! \brief Retrieves the pointer for a constant entry with the name name if + * it exists. */ + const ParameterEntry* getEntryPtr(const std::string& name) const; + + //@} + + //! @name Parameter removal functions + //@{ + + /** \brief Remove a parameter (does not depend on the type of the + * parameter). + * + * \param name [in] The name of the parameter to remove + * + * \param throwIfNotExists [in] If true then if the parameter with + * the name name does not exist then a std::exception will be + * thrown! + * + * \returns Returns true if the parameter was removed, and + * false if the parameter was not removed (false return + * value possible only if throwIfExists==false). + */ + bool remove( + std::string const& name, bool throwIfNotExists = true + ); + + //@} + + //! @name Sublist Functions + //@{ + + /*! \brief Creates an empty sublist and returns a reference to the sublist + * \c name. If the list already exists, returns reference to that + * sublist. If the name exists but is not a sublist, an std::exception is + * thrown. + */ + ParameterList& sublist( + const std::string& name, bool mustAlreadyExist = false + ,const std::string& docString = "" + ); + + /*! \brief Return a const reference to an existing sublist \c name. If the + * list does not already exist or the name exists but is not a sublist, an + * std::exception is thrown. + */ + const ParameterList& sublist(const std::string& name) const; + + //@} + + //! @name Attribute Functions + //@{ + + /*! \brief Query the name of this parameter list. */ + const std::string& name() const; + + /*! \brief Query the existence of a parameter. \return "true" if a + parameter with this \c name exists, else "false". Warning, this + function should almost never be used! Instead, consider using + getEntryPtr() instead. + */ + bool isParameter(const std::string& name) const; + + /*! \brief Query the existence of a parameter and whether it is a parameter + list. \return "true" if a parameter with this \c name exists and is + itself a parameter list, else "false". Warning, this function should + almost never be used! Instead, consider using getEntryPtr() instead. + */ + bool isSublist(const std::string& name) const; + + /*! \brief Query the existence and type of a parameter. \return "true" is a + parameter with this \c name exists and is of type \c T, else "false". + \note The syntax for calling this method is: list.template + isType( "Iters" ) . Warning, this function should almost never + be used! Instead, consider using getEntryPtr() instead. + */ + template + bool isType(const std::string& name) const; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + /*! \brief Query the existence and type of a parameter. + * + * \return "true" is a parameter with this \c name exists and is of type \c + * T, else "false". + * + * \note It is not recommended that this method be used directly! + * + * Please use either the helper function isParameterType or + * non-nominal isType method. + */ + template + bool isType(const std::string& name, T* ptr) const; +#endif + + //@} + + //! @name I/O Functions + //@{ + + /*! \brief Printing method for parameter lists which takes an print options + * object.*/ + std::ostream& print(std::ostream& os, const PrintOptions &printOptions) const; + + /*! \brief Printing method for parameter lists. Indenting is used to indicate + parameter list hierarchies. */ + std::ostream& print(std::ostream& os, int indent = 0, bool showTypes = false, bool showFlags = true ) const; + + //! Print out unused parameters in the ParameterList. + void unused(std::ostream& os) const; + + //! Create a single formated std::string of all of the zero-level parameters in this list + std::string currentParametersString() const; + + //@} + + //! @name Read-only access to the iterator + //@{ + + //! An iterator pointing to the first entry + ConstIterator begin() const ; + + //! An iterator pointing beyond the last entry + ConstIterator end() const ; + + //! Access to ParameterEntry (i.e., returns i->second) + const ParameterEntry& entry(ConstIterator i) const; + + //! Access to name (i.e., returns i->first) + const std::string& name(ConstIterator i) const; + + //@} + + //! @name Validation Functions + //@{ + + /** \brief Validate the parameters in this list given valid selections in + * the input list. + * + * \param validParamList [in] This is the list that the parameters and + * sublist in *this are compared against. + * + * \param depth [in] Determines the number of levels of depth that the + * validation will recurse into. A value of dpeth=0 means that + * only the top level parameters and sublists will be checked. Default: + * depth = large number. + * + * \param validateUsed [in] Determines if parameters that have been used are + * checked against those in validParamList. Default: + * validateDefaults = VALIDATE_DEFAULTS_ENABLED. + * + * \param validateDefaults [in] Determines if parameters set at their + * default values using get(name,defaultVal) are checked against + * those in validParamList. Default: validateDefaults = + * VALIDATE_DEFAULTS_ENABLED. + * + * If a parameter in *this is not found in validParamList + * then an std::exception of type + * Exceptions::InvalidParameterName will be thrown which will + * contain an excellent error message returned by excpt.what(). If + * the parameter exists but has the wrong type, then an std::exception type + * Exceptions::InvalidParameterType will be thrown. If the + * parameter exists and has the right type, but the value is not valid then + * an std::exception type Exceptions::InvalidParameterValue will be + * thrown. + * + * Recursive validation stops when:
      + * + *
    • The maxinum depth is reached + * + *
    • A sublist note in validParamList has been marked with the + * disableRecursiveValidation() function, or + * + *
    • There are not more parameters or sublists left in *this + * + *
    + * + * A breath-first search is performed to validate all of the parameters in + * one sublist before moving into nested subslist. + */ + void validateParameters( + ParameterList const& validParamList, + int const depth = 1000, + EValidateUsed const validateUsed = VALIDATE_USED_ENABLED, + EValidateDefaults const validateDefaults = VALIDATE_DEFAULTS_ENABLED + ) const; + + /** \brief Validate the parameters in this list given valid selections in + * the input list and set defaults for those not set. + * + * \param validParamList [in] This is the list that the parameters and + * sublist in *this are compared against. + * + * \param depth [in] Determines the number of levels of depth that the + * validation will recurse into. A value of dpeth=0 means that + * only the top level parameters and sublists will be checked. Default: + * depth = large number. + * + * If a parameter in *this is not found in validParamList + * then an std::exception of type Exceptions::InvalidParameterName will + * be thrown which will contain an excellent error message returned by + * excpt.what(). If the parameter exists but has the wrong type, + * then an std::exception type Exceptions::InvalidParameterType will be + * thrown. If the parameter exists and has the right type, but the value is + * not valid then an std::exception type + * Exceptions::InvalidParameterValue will be thrown. If a + * parameter in validParamList does not exist in *this, + * then it will be set at its default value as determined by + * validParamList. + * + * Recursive validation stops when:
      + * + *
    • The maxinum depth is reached + * + *
    • A sublist note in validParamList has been marked with the + * disableRecursiveValidation() function, or + * + *
    • There are not more parameters or sublists left in *this + * + *
    + * + * A breath-first search is performed to validate all of the parameters in + * one sublist before moving into nested subslist. + */ + void validateParametersAndSetDefaults( + ParameterList const& validParamList, + int const depth = 1000 + ); + + //@} + +private: // Functions + + //! An iterator pointing to the first entry + Iterator nonconstBegin(); + //! An iterator pointing beyond the last entry + Iterator nonconstEnd(); + //! Access to ParameterEntry (i.e., returns i->second) + ParameterEntry& entry(Iterator i); + //! Validate that a parameter exists + void validateEntryExists( const std::string &funcName, const std::string &name, const ParameterEntry *entry ) const; + //! Validate that a type is the same + template + void validateEntryType( const std::string &funcName, const std::string &name, const ParameterEntry &entry ) const; + //! Update sublist names recursively + void updateSubListNames(int depth = 0); + +private: // Data members + + //! Name of the (sub)list + std::string name_; + //! Parameter list + Map params_; + //! Validate into list or not + bool disableRecursiveValidation_; + +}; + + +/** \brief Nonmember constructor. */ +inline +RCP parameterList() +{ + return rcp(new ParameterList); +} + + +/** \brief Nonmember constructor. */ +inline +RCP parameterList(const std::string &name) +{ + return rcp(new ParameterList(name)); +} + +/** \brief Nonmember constructor. */ +inline +RCP parameterList(const ParameterList& source) +{ + return rcp(new ParameterList(source)); +} + + + +/** \brief Traits specialization. + * + * \relates ParameterList + */ +template<> +class TypeNameTraits { +public: + static std::string name() { return "ParameterList"; } +}; + +/** \brief Returns true if two parameter lists are the same. + * + * \relates ParameterList + */ +bool operator==( const ParameterList& list1, const ParameterList& list2 ); + +/** \brief Returns true if two parameter lists are not
    the same. + * + * \relates ParameterList + */ +inline +bool operator!=( const ParameterList& list1, const ParameterList& list2 ) +{ + return !( list1 == list2 ); +} + +/** \brief Returns true if two parameter lists have the same values. + * + * Two parameter lists may have the same values but may not be identical. For + * example, two parameters can have the same values but not have the same + * documentation strings or the same validators. + * + * \relates ParameterList + */ +bool haveSameValues( const ParameterList& list1, const ParameterList& list2 ); + +// ///////////////////////////////////////////////////// +// Inline and Template Function Definitions + +inline +ParameterList& ParameterList::setName( const std::string &name ) +{ + name_ = name; + return *this; +} + +// Set functions + +template +inline +ParameterList& ParameterList::set( + std::string const& name, T const& value, std::string const& docString + ,RCP const& validator + ) +{ + ParameterEntry &entry = params_[name]; // Will add the entry if not exists + entry.setValue(value,false,docString,validator); + // Validate the value *after* you set it. It is important to use + // entry.validator() instead of validator since validator might be null! + if(entry.validator().get()) + entry.validator()->validate(entry,name,this->name()); + return *this; +} + +inline +ParameterList& ParameterList::set( + std::string const& name, char value[], std::string const& docString + ,RCP const& validator + ) +{ return set( name, std::string(value), docString, validator ); } + +inline +ParameterList& ParameterList::set( + const std::string& name, const char value[], const std::string &docString + ,RCP const& validator + ) +{ return set( name, std::string(value), docString, validator ); } + +inline +ParameterList& ParameterList::set( + std::string const& name, ParameterList const& value, std::string const& docString + ) +{ + sublist(name) = value; + return *this; +} + +inline +ParameterList& ParameterList::setEntry(std::string const& name, ParameterEntry const& entry) +{ + params_[name] = entry; + return *this; +} + +// Get functions + +template +T& ParameterList::get(const std::string& name, T def_value) +{ + ConstIterator i = params_.find(name); + + // The parameter was not found, add it to the list + if (i == params_.end()) { + params_[name].setValue(def_value, true); + i = params_.find(name); + } else { + // The parameter was found, make sure it is the same type as T. + this->template validateEntryType("get",name,entry(i)); + } + + // Return the value of the parameter + return getValue(entry(i)); +} + +inline +std::string& ParameterList::get(const std::string& name, char def_value[]) +{ return get(name, std::string(def_value)); } + +inline +std::string& ParameterList::get(const std::string& name, const char def_value[]) +{ return get(name, std::string(def_value)); } + +template +T& ParameterList::get(const std::string& name) +{ + ParameterEntry *entry = this->getEntryPtr(name); + validateEntryExists("get",name,entry); + this->template validateEntryType("get",name,*entry); + return getValue(*entry); +} + +template +const T& ParameterList::get(const std::string& name) const +{ + const ParameterEntry *entry = this->getEntryPtr(name); + validateEntryExists("get",name,entry); + this->template validateEntryType("get",name,*entry); + return getValue(*entry); +} + +template +inline +T* ParameterList::getPtr(const std::string& name) +{ + ConstIterator i = params_.find(name); + if ( i == params_.end() || entry(i).getAny().type() != typeid(T) ) + return NULL; + return &getValue(entry(i)); +} + +template +inline +const T* ParameterList::getPtr(const std::string& name) const +{ + ConstIterator i = params_.find(name); + if ( i == params_.end() || entry(i).getAny().type() != typeid(T) ) + return NULL; + return &getValue(entry(i)); +} + +inline +ParameterEntry& ParameterList::getEntry(const std::string& name) +{ + ParameterEntry *entry = this->getEntryPtr(name); + validateEntryExists("get",name,entry); + return *entry; +} + +inline +const ParameterEntry& ParameterList::getEntry(const std::string& name) const +{ + const ParameterEntry *entry = this->getEntryPtr(name); + validateEntryExists("get",name,entry); + return *entry; +} + +inline +ParameterEntry* +ParameterList::getEntryPtr(const std::string& name) +{ + Map::iterator i = params_.find(name); + if ( i == params_.end() ) + return NULL; + return &entry(i); +} + +inline +const ParameterEntry* +ParameterList::getEntryPtr(const std::string& name) const +{ + ConstIterator i = params_.find(name); + if ( i == params_.end() ) + return NULL; + return &entry(i); +} + +// Attribute Functions + +inline +const std::string& ParameterList::name() const +{ + return name_; +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +bool ParameterList::isType(const std::string& name, T* ptr) const +{ + ConstIterator i = params_.find(name); + // If parameter doesn't exist, return false. + if (i == params_.end()) + return false; + return entry(i).getAny().type() == typeid(T); +} +#endif + +template +bool ParameterList::isType(const std::string& name) const +{ + ConstIterator i = params_.find(name); + // If parameter doesn't exist, return false. + if (i == params_.end()) + return false; + return entry(i).getAny().type() == typeid(T); +} + + +// private + + +template +inline +void ParameterList::validateEntryType( + const std::string &funcName, const std::string &name, + const ParameterEntry &entry + ) const +{ + TEST_FOR_EXCEPTION_PURE_MSG( + (entry.getAny().type() != typeid(T)) + && (entry.getAny().typeName() != TypeNameTraits::name()) + , Exceptions::InvalidParameterType + ,"Error! An attempt was made to access parameter \""<name()<<"\"" + "\nusing the incorrect type \""<::name()<<"\"!" + ); + // 2007/11/27: rabartl: Above, I removed the ifdef for ENABLE_SHARED since + // the g++ compiler flagged this as non-ansi code. We will leave the second + // test for the name. This should not be a performance problem since the + // most comon use case will be for validate to pass in which case the second + // comparison for the name will never be executed since the first typeid(T) + // test will pass. +} + +// ////////////////////////////////////// +// Helper functions + +/*! \relates ParameterList + \brief A templated helper function for getting a parameter from a non-const list. + This helper function prevents the need for giving a nominal value of the specific template type. + + \note The syntax for calling this function is: getParameter( list, "Iters" ) +*/ +template +T& getParameter( ParameterList& l, const std::string& name ) +{ + return l.template get(name); +} + +/*! \relates ParameterList + \brief A shorter name for getParameter(). + + \note The syntax for calling this function is: get( list, "Iters" ) +*/ +template +inline +T& get( ParameterList& l, const std::string& name ) +{ + return getParameter(l,name); +} + +/*! \relates ParameterList + \brief A templated helper function for getting a parameter from a const list. + This helper function prevents the need for giving a nominal value of the specific template type. + + \note The syntax for calling this function is: getParameter( list, "Iters" ) +*/ +template +const T& getParameter( const ParameterList& l, const std::string& name ) +{ + return l.template get(name); +} + +/*! \relates ParameterList + \brief A templated helper function for getting a pointer to a parameter from + a non-const list, if it exists. This helper function prevents the need for + giving a nominal value of the specific template type. + \note The syntax for calling this function is: + getParameterPtr(list,"Iters") +*/ +template +inline +T* getParameterPtr( ParameterList& l, const std::string& name ) +{ + return l.template getPtr(name); +} + +/*! \relates ParameterList + \brief A templated helper function for getting a pointer to a parameter from + a non-const list, if it exists. This helper function prevents the need for + giving a nominal value of the specific template type. + \note The syntax for calling this function is: + getParameterPtr(list,"Iters") +*/ +template +inline +const T* getParameterPtr( const ParameterList& l, const std::string& name ) +{ + return l.template getPtr(name); +} + +/*! \relates ParameterList + \brief A templated helper function for determining the type of a parameter entry for a non-const list. + This helper function avoids the need for giving a nominal value of the specific template type. + + \note The syntax for calling this function is: isParameterType( list, "Iters" ) +*/ +template +inline +bool isParameterType( ParameterList& l, const std::string& name ) +{ + return l.isType( name, (T*)NULL ); +} + +/*! \relates ParameterList + \brief A templated helper function for determining the type of a parameter entry for a const list. + This helper function avoids the need for giving a nominal value of the specific template type. + + \note The syntax for calling this function is: isParameterType( list, "Iters" ) +*/ +template +inline +bool isParameterType( const ParameterList& l, const std::string& name ) +{ + return l.isType( name, (T*)NULL ); +} + +/** \brief Set a std::string parameter representation of an array. + * + * \param paramName [in] The name of the parameter containing the std::string + * representation of the array. + * + * \param array [in] The array that will be set as a std::string parameter. + * + * \param paramList [in/out] The parameter list that the array will be set on. + * + * \relates ParameterList + */ +template +void setStringParameterFromArray( + const std::string ¶mName + ,const Array &array + ,ParameterList *paramList + ) +{ + TEST_FOR_EXCEPT(!paramList); + paramList->set(paramName,toString(array)); +} + +/** \brief Get an Array object (with entries of type T) from a + * parameter holding a std::string representation of the array. + * + * \param paramList [in] The parameter list to extract the parameter array + * from. + * + * \param paramName [in] The name of the parameter containing the std::string + * representation of the array. + * + * \param arrayDim [in] If arrayDim >= 0, then the read in array must + * be equal to this dimension, or an std::exception will be thrown. If + * arrayDim < 0, then an array of any dimension will be returned. + * The default is -1 and therefore no array length validation will be + * performed. + * + * \param mustExist [in] If mustExist==true, then the parameter + * paramName must exist and must contain a valid array, or an + * std::exception is thrown. If mustExist==false, and if the + * parameter paramName does not exist or contains an empty array + * std::string value, then an empty array object will be returned. + * + * \returns an array object if an std::exception is not thrown. If + * mustExist==false and the parameter does not exist, then an empty + * array object will be returned. If mustExist==true and + * arrayDim < 0, then if the parameter paramName exists and + * its array value is valid, then the converted array, of any size, will be + * returned. If mustExist==true and arrayDim >= 0 then an + * array of dimension arrayDim will be returned if an std::exception is + * not thrown. + * + * Exceptions: + * + *
      + * + *
    • Exceptions::InvalidParameterName will be thrown if + * mustExist==true and the parameter paramName does not + * exist in paramList + * + *
    • Exceptions::InvalidParameterType will be thrown if the + * parameter exists but does not have a value type of std::string. + * + *
    • Exceptions::InvalidParameterValue will be thrown in the following cases: + * + *
        + *
      • If the parameter paramName exists but the array in std::string form + * is not formated correctly. + *
      • If arrayDim >= 0 and the read in array dimension dies not equal + * arrayDim + *
      + * + *
    + * + * Detailed Description: + * + * This function allows Array objects to be read in from a + * parameter with a std::string representation of the array. The templated function + * Teuchos::fromStringToArray() (see documentation for + * Teuchos::Array) is used to parse the std::string representation and + * return the array object (see this function's documentation for details on + * what the formatting of the array std::string must be and what can be handled and + * what can not be handled. + * + * \relates ParameterList + */ +template +Array getArrayFromStringParameter( + const ParameterList ¶mList + ,const std::string ¶mName + ,const int arrayDim = -1 + ,const bool mustExist = true + ) +{ + std::string arrayStr; + if(mustExist) { + arrayStr = getParameter(paramList,paramName); + } + else { + const std::string + *arrayStrPtr = getParameterPtr(paramList,paramName); + if(arrayStrPtr) { + arrayStr = *arrayStrPtr; + } + else { + return Array(); // Return an empty array + } + } + Array a; + try { + a = fromStringToArray(arrayStr); + } + catch( const InvalidArrayStringRepresentation &except ) { + TEST_FOR_EXCEPTION_PURE_MSG( + true, Exceptions::InvalidParameterValue + ,"Error! The parameter \""<0 && arrayDim>=0 ) && static_cast(a.size())!=arrayDim ) + ,Exceptions::InvalidParameterValue + ,"Error! The parameter \""< sublist( + const RCP ¶mList, const std::string& name, bool mustAlreadyExist = false + ) +{ + RCP + sublist = Teuchos::rcp(¶mList->sublist(name,mustAlreadyExist),false); + set_extra_data(paramList,"masterParamList",&sublist); + return sublist; +} + +/*! \relates ParameterList + \brief Return a RCP to a sublist in another RCP-ed parameter list. +*/ +inline +RCP sublist( + const RCP ¶mList, const std::string& name + ) +{ + RCP + sublist = Teuchos::rcp(¶mList->sublist(name),false); + set_extra_data(paramList,"masterParamList",&sublist); + return sublist; +} + +/*! \relates ParameterList + \brief Output stream operator for handling the printing of the parameter list. +*/ +inline std::ostream& operator<<(std::ostream& os, const ParameterList& l) +{ + return l.print(os); +} + +} // end of Teuchos namespace + +#endif + + diff --git a/fastlib/trilinos/include/Teuchos_ParameterListAcceptor.hpp b/fastlib/trilinos/include/Teuchos_ParameterListAcceptor.hpp new file mode 100644 index 0000000000..84deccb057 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterListAcceptor.hpp @@ -0,0 +1,127 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_PARAMETER_LIST_ACCEPTOR_HPP +#define TEUCHOS_PARAMETER_LIST_ACCEPTOR_HPP + +#include "Teuchos_ConfigDefs.hpp" + +namespace Teuchos { + +class ParameterList; +template class RCP; + +/** \brief Base class objects that can accept a parameter list. + * + * ToDo: Finish Documentation! + */ +class ParameterListAcceptor { +public: + + /** \brief . */ + virtual ~ParameterListAcceptor(); + + //! @name Pure virtual functions that must be overridden in subclasses + //@{ + + /** \brief Set parameters from a parameter list and return with default values. + * + * \param paramList [in] On input contains the parameters set by the client. + * Note that *paramList may have parameters set to their + * default values added while the list is being parsed either right + * away or later. + * + * Preconditions:
      + *
    • paramList.get() != NULL + *
    + * + * Postconditions:
      + *
    • this->getParameterList().get() == paramList.get() + *
    + * + * This is parameter list is "remembered" by *this object until it is + * unset using unsetParameterList(). + * + * Note: When this parameter list is passed in it is assumed that the + * client has finished setting all of the values that they want to set so + * that the list is completely ready to read (and be validated) by + * *this object. If the client is to change this parameter list by + * adding new options or changing the value of current options, the behavior + * of *this object is undefined. This is because, the object may + * read the options from *paramList right away or may wait to read + * some options until a later time. There should be no expectation that if + * an option is changed by the client that this will automatically be + * recognized by *this object. To change even one parameter, this + * function must be called again, with the entire sublist. + */ + virtual void setParameterList(RCP const& paramList) = 0; + + /** \brief Get the parameter list that was set using setParameterList(). + */ + virtual RCP getParameterList() = 0; + + /** \brief Unset the parameter list that was set using setParameterList(). + * + * This just means that the parameter list that was set using + * setParameterList() is detached from this object. This does not + * mean that the effect of the parameters is undone. + * + * Postconditions:
      + *
    • this->getParameterList().get() == NULL + *
    + */ + virtual RCP unsetParameterList() = 0; + + //@} + + //! @name Virtual functions with default implementation + //@{ + + /** \brief Get const version of the parameter list that was set using setParameterList(). + * + * The default implementation returns: + \code + return const_cast(this)->getParameterList(); + \endcode + */ + virtual RCP getParameterList() const; + + /** \brief Return a const parameter list of all of the valid parameters that + * this->setParameterList(...) will accept. + * + * The default implementation returns Teuchos::null. + */ + virtual RCP getValidParameters() const; + + //@} + +}; + +} // end namespace Teuchos + +#endif // TEUCHOS_PARAMETER_LIST_ACCEPTOR_HPP diff --git a/fastlib/trilinos/include/Teuchos_ParameterListAcceptorDefaultBase.hpp b/fastlib/trilinos/include/Teuchos_ParameterListAcceptorDefaultBase.hpp new file mode 100644 index 0000000000..7a66c8787c --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterListAcceptorDefaultBase.hpp @@ -0,0 +1,118 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_PARAMETER_LIST_ACCEPTOR_DEFAULT_BASE_HPP +#define TEUCHOS_PARAMETER_LIST_ACCEPTOR_DEFAULT_BASE_HPP + +#include "Teuchos_ParameterListAcceptor.hpp" +#include "Teuchos_RCP.hpp" + + +namespace Teuchos { + + +/** \brief Intermediate node base class for objects that accept parameter lists + * that implements some of the needed behavior automatically. + * + * Subclasses just need to implement setParameterList() and + * getValidParameters(). The underlying paraemeter list is accessed + * using the protected members setMyParamList() and + * getMyParamList(). + */ +class ParameterListAcceptorDefaultBase : virtual public ParameterListAcceptor { +public: + + /** \name Overridden from ParameterListAcceptor */ + //@{ + + /** \brief . */ + RCP getParameterList(); + /** \brief . */ + RCP unsetParameterList(); + /** \brief . */ + RCP getParameterList() const; + + //@} + +protected: + + /** \name Protected accessors to actual parameter list object. */ + //@{ + + /** \brief . */ + void setMyParamList( const RCP ¶mList ); + + /** \brief . */ + RCP getMyParamList(); + + /** \brief . */ + RCP getMyParamList() const; + + //@} + +private: + + RCP paramList_; + +}; + + +// +// Inline definitions +// + + +inline +void ParameterListAcceptorDefaultBase::setMyParamList( + const RCP ¶mList + ) +{ + paramList_ = paramList; +} + + +inline +RCP +ParameterListAcceptorDefaultBase::getMyParamList() +{ + return paramList_; +} + + +inline +RCP +ParameterListAcceptorDefaultBase::getMyParamList() const +{ + return paramList_; +} + + +} // end namespace Teuchos + + +#endif // TEUCHOS_PARAMETER_LIST_ACCEPTOR_DEFAULT_BASE_HPP diff --git a/fastlib/trilinos/include/Teuchos_ParameterListExceptions.hpp b/fastlib/trilinos/include/Teuchos_ParameterListExceptions.hpp new file mode 100644 index 0000000000..81963261a1 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterListExceptions.hpp @@ -0,0 +1,69 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +#ifndef TEUCHOS_PARAMETER_LIST_EXCEPTIONS_H +#define TEUCHOS_PARAMETER_LIST_EXCEPTIONS_H + +#include "Teuchos_ConfigDefs.hpp" + +namespace Teuchos { + +namespace Exceptions { + +/** \brief . + * \relates ParameterList + */ +class InvalidParameter : public std::logic_error +{public: InvalidParameter(const std::string& what_arg) : std::logic_error(what_arg) {}}; + +/** \brief . + * \relates ParameterList + */ +class InvalidParameterName : public InvalidParameter +{public: InvalidParameterName(const std::string& what_arg) : InvalidParameter(what_arg) {}}; + +/** \brief . + * \relates ParameterList + */ +class InvalidParameterType : public InvalidParameter +{public: InvalidParameterType(const std::string& what_arg) : InvalidParameter(what_arg) {}}; + +/** \brief . + * \relates ParameterList + */ +class InvalidParameterValue : public InvalidParameter +{public: InvalidParameterValue(const std::string& what_arg) : InvalidParameter(what_arg) {}}; + +} // namespace Exceptions + +} // end of Teuchos namespace + +#endif // TEUCHOS_PARAMETER_LIST_EXCEPTIONS_H + + diff --git a/fastlib/trilinos/include/Teuchos_ParameterListNonAcceptor.hpp b/fastlib/trilinos/include/Teuchos_ParameterListNonAcceptor.hpp new file mode 100644 index 0000000000..29ca3f20a4 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterListNonAcceptor.hpp @@ -0,0 +1,66 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_PARAMETER_LIST_NON_ACCEPTOR_HPP +#define TEUCHOS_PARAMETER_LIST_NON_ACCEPTOR_HPP + +#include "Teuchos_ParameterListAcceptorDefaultBase.hpp" + +namespace Teuchos { + + +/** \brief Mix-in implementation subclass to be inherited by concrete + * subclasses who's interface says that they take a parameter list but do not + * have any parameters yet. + * + * ToDo: Finish documention. + */ +class ParameterListNonAcceptor + : virtual public ParameterListAcceptorDefaultBase +{ +public: + + + /** \name Overridden from ParameterListAcceptor */ + //@{ + + /** \brief Accepts a parameter list but asserts that it is empty. */ + void setParameterList(RCP const& paramList); + + /** \brief Returns a non-null but empty parameter list. */ + RCP getValidParameters() const; + + //@} + +}; + + +} // end namespace Teuchos + + +#endif // TEUCHOS_PARAMETER_LIST_NON_ACCEPTOR_HPP diff --git a/fastlib/trilinos/include/Teuchos_ParameterXMLFileReader.hpp b/fastlib/trilinos/include/Teuchos_ParameterXMLFileReader.hpp new file mode 100644 index 0000000000..3e1c21972c --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ParameterXMLFileReader.hpp @@ -0,0 +1,56 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef Teuchos_PARAMETERXMLFILEREADER_H +#define Teuchos_PARAMETERXMLFILEREADER_H + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_FileInputSource.hpp" +#include "Teuchos_XMLParameterListReader.hpp" + + +namespace Teuchos +{ + /** + * Reader for getting parameter lists from XML files + */ + class ParameterXMLFileReader + { + public: + /** \brief Constructor */ + ParameterXMLFileReader(const std::string& filename); + + /** */ + ParameterList getParameters() const ; + private: + FileInputSource fis_; + }; + +} +#endif + diff --git a/fastlib/trilinos/include/Teuchos_PerformanceMonitorBase.hpp b/fastlib/trilinos/include/Teuchos_PerformanceMonitorBase.hpp new file mode 100644 index 0000000000..4a359be625 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_PerformanceMonitorBase.hpp @@ -0,0 +1,146 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_PERFORMANCEMONITORBASE_H +#define TEUCHOS_PERFORMANCEMONITORBASE_H + +/*! \file Teuchos_PerformanceMonitorBase.hpp + \brief Provides common capabilities for collecting and reporting + performance data across processors +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_MPIComm.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_PerformanceMonitorUtils.hpp" +#include "Teuchos_TableFormat.hpp" + +namespace Teuchos +{ + +/** \brief Provides common capabilities for collecting and reporting + * performance data across processors. + * + * PerformanceMonitorBase is templated on a counter type (which might be a + * timer or a flop counter). The common capability of the counter type is a + * counter for the number of calls. Derived counter types can supply + * additional features. + * + * A PerformanceMonitorBase will increment its call counter upon + * every ctor call. Derived types might do more upon construction or + * destruction; for example, a timer will start upon construction + * and stop upon destruction. + * + * The class keeps a static list of all counters created using + * the getNewCounter() method during the course of a run. Counts + * from this list can then be printed out at the end of the run. + * + * The minimum requirements on the counter for use in the PerformanceMonitorBase + * are the following methods: + * \code + * // add one to number of calls + * void incrementNumCalls() + * // return the number of calls + * int numCalls() const + * // indicate whether the counter is already running + * bool isRunning() const + * \endcode + */ +template +class PerformanceMonitorBase +{ +public: + + /** \brief Construct with a counter. */ + PerformanceMonitorBase(T& counter, bool reset=false) + : counter_(counter), isRecursiveCall_(counter_.isRunning()) + { + counter_.incrementNumCalls(); + } + + /** \brief The dtor for the base class does nothing. */ + virtual ~PerformanceMonitorBase() {} + + /** \brief Create a new counter with the specified name and append it to a + * global list of counters of this type. + * + * New counters should usually be created in this way rather than through a + * direct ctor call so that they can be appended to the list. + */ + static RCP getNewCounter(const std::string& name) + { + RCP rtn = rcp(new T(name), true); + counters().append(rtn); + return rtn; + } + + /** \brief Get the format that will be used to print a summary of + * results. + */ + static TableFormat& format() + { + static RCP rtn=rcp(new TableFormat()); + return *rtn; + } + +protected: + + /** \brief Access to the counter. */ + const T& counter() const { return counter_; } + + /** \brief Access to the counter. */ + T& counter() { return counter_; } + + /** \brief Indicate whether the current call is recursive. + * + * This can matter in cases such as timing where we don't want to start and + * stop timers multiple times within a single call stack. + */ + bool isRecursiveCall() const { return isRecursiveCall_; } + + /** \brief Use the "Meyers Trick" to create static data safely. */ + static Array >& counters() + { + static Array > rtn; + return rtn; + } + +private: + + T& counter_; + + bool isRecursiveCall_; + +}; + + +} // namespace Teuchos + + +#endif diff --git a/fastlib/trilinos/include/Teuchos_PerformanceMonitorUtils.hpp b/fastlib/trilinos/include/Teuchos_PerformanceMonitorUtils.hpp new file mode 100644 index 0000000000..9e64952d70 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_PerformanceMonitorUtils.hpp @@ -0,0 +1,113 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_PERFORMANCEMONITORUTILS_H +#define TEUCHOS_PERFORMANCEMONITORUTILS_H + +/*! \file Teuchos_PerformanceMonitorUtils.hpp + \brief Provides common capabilities for collecting and reporting + performance data across processors +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_MPIComm.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_Array.hpp" + +namespace Teuchos +{ + /** + * \brief Types of reduction operations on performance metrics. + * Add other operations if you like. + */ + enum EMetricReduction {ELocal, ETotal, EMin, EMax, EAvg} ; + + + + /** + * \brief Provides common capabilities for collecting and reporting + * performance data across processors + */ + class PerformanceMonitorUtils + { + public: + + /** + * \brief Synchronizes lists of metric names (e.g., timer names) + * across processors. This is necessary because some functions + * may not have been invoked on some processors, so that their + * named timers/counters aren't created on that processor. + * This function does a set union of all names created on all processors. + * It is called by synchValues(). + * + * \param comm [in] the communicator over which name lists are + * being synchronized + * \param localNames [in] the names appearing on the local processor + * \param allNames [out] the set union of name lists from all processors + */ + static void synchNames(const MPIComm& comm, + const Array& localNames, + Array& allNames); + + /** + * \brief Creates zero values for metrics absent on this + * processor but present on other processors. This function uses + * a call to synchNames() to inform this processor + * of the existence of other metrics on other processors. + * + * \param comm [in] the communicator over which name lists are + * being synchronized + * \param localNames [in] the names appearing on the local processor + * \param localValues [in] the values appearing on the local processor + * \param allNames [out] the set union of name lists from all processors + * \param allValues [out] the metric values from all processors + */ + static void synchValues(const MPIComm& comm, + const Array& localNames, + const Array >& localValues, + Array& allNames, + Array >& allValues); + + /** \brief Compute reduced performance metrics across processors, for + * example, min, max, or total times or flop counts. + * \param comm [in] The MPIComm object representing the communicator + * on which the reduction is to be done. + * \param reductionType [in] the reduction operation to be performed + * \param localVals [in] The metrics on this processor (after + * synchronization through a call to synchValues()) + * \param reducedVals [out] The reduced metrics + */ + static void reduce(const MPIComm& comm, + const EMetricReduction& reductionType, + const Array& localVals, + Array& reducedVals); + + }; + +} +#endif diff --git a/fastlib/trilinos/include/Teuchos_Polynomial.hpp b/fastlib/trilinos/include/Teuchos_Polynomial.hpp new file mode 100644 index 0000000000..7dd58e46e1 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Polynomial.hpp @@ -0,0 +1,187 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_POLYNOMIAL_HPP +#define TEUCHOS_POLYNOMIAL_HPP + +#include "Teuchos_PolynomialDecl.hpp" +#include "Teuchos_ScalarTraits.hpp" + +template +Teuchos::Polynomial::Polynomial(unsigned int deg, + const CoeffT& cloneCoeff, + unsigned int reserve) : + d(deg) +{ + if (reserve > d) + sz = reserve+1; + else + sz = d+1; + + coeff.resize(sz); + for (unsigned int i=0; i::clone(cloneCoeff); +} + +template +Teuchos::Polynomial::Polynomial(unsigned int deg, + unsigned int reserve) : + d(deg) +{ + if (reserve > d) + sz = reserve+1; + else + sz = d+1; + + coeff.resize(sz); +} + +template +Teuchos::Polynomial::~Polynomial() +{ +} + +template +void +Teuchos::Polynomial::setDegree(unsigned int deg) +{ + d = deg; + if (d+1 > sz) { + coeff.resize(d+1); + if (coeff[0] != Teuchos::null) { + for (unsigned int i=sz; i::clone(*coeff[0]); + } + sz = d+1; + } +} + +template +Teuchos::RCP +Teuchos::Polynomial::getCoefficient(unsigned int i) +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION(i > d, + std::out_of_range, + "Polynomial::getCoefficient(i): " << + "Error, coefficient i = " << i << + " is not in range, degree = " << d << "." ); +#endif + return coeff[i]; +} + +template +Teuchos::RCP +Teuchos::Polynomial::getCoefficient(unsigned int i) const +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION(i > d, + std::out_of_range, + "Polynomial::getCoefficient(i): " << + "Error, coefficient i = " << i << + " is not in range, degree = " << d << "." ); +#endif + return coeff[i]; +} + +template +void +Teuchos::Polynomial::setCoefficient(unsigned int i, const CoeffT& v) +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION(i > d, + std::out_of_range, + "Polynomial::setCoefficient(i,v): " << + "Error, coefficient i = " << i << + " is not in range, degree = " << d << "." ); + TEST_FOR_EXCEPTION(coeff[i] == Teuchos::null, + std::runtime_error, + "Polynomial::setCoefficient(i,v): " << + "Error, coefficient i = " << i << " is null!"); +#endif + PolynomialTraits::copy(v, coeff[i].get()); +} + +template +void +Teuchos::Polynomial::setCoefficientPtr( + unsigned int i, + const Teuchos::RCP& v) +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION(i > d, + std::out_of_range, + "Polynomial::setCoefficientPtr(i,v): " << + "Error, coefficient i = " << i << + " is not in range, degree = " << d << "." ); +#endif + coeff[i] = v; +} + +template +void +Teuchos::Polynomial::evaluate( + typename Teuchos::Polynomial::scalar_type t, + CoeffT* x, CoeffT* xdot) const +{ + bool evaluate_xdot = (xdot != NULL); + +#ifdef TEUCHOS_DEBUG + for (unsigned int i=0; i<=d; i++) + TEST_FOR_EXCEPTION(coeff[i] == Teuchos::null, + std::runtime_error, + "Polynomial::evaluate(): " << + "Error, coefficient i = " << i << " is null!"); +#endif + + // Initialize x, xdot with coeff[d] + PolynomialTraits::copy(*coeff[d], x); + if (evaluate_xdot) { + if (d > 0) + PolynomialTraits::copy(*coeff[d], xdot); + else + PolynomialTraits::assign( + xdot, + Teuchos::ScalarTraits::zero()); + } + + // If this is a degree 0 polynomial, we're done + if (d == 0) + return; + + for (int k=d-1; k>=0; --k) { + // compute x = coeff[k] + t*x + PolynomialTraits::update(x, *coeff[k], t); + + // compute xdot = x + t*xdot + if (evaluate_xdot && k > 0) + PolynomialTraits::update(xdot, *x, t); + } +} + +#endif // TEUCHOS_VECTOR_POLYNOMIAL_HPP diff --git a/fastlib/trilinos/include/Teuchos_PolynomialDecl.hpp b/fastlib/trilinos/include/Teuchos_PolynomialDecl.hpp new file mode 100644 index 0000000000..3f87f85b19 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_PolynomialDecl.hpp @@ -0,0 +1,153 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_POLYNOMIAL_DECL_HPP +#define TEUCHOS_POLYNOMIAL_DECL_HPP + +#include "Teuchos_Describable.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_PolynomialTraits.hpp" + +namespace Teuchos { + + //! Lightweight container class to represent a simple polynomial. + /*! + * This class represents a simple polynomial of the form: + * \f[ + * x(t) = \sum_{i=0}^d x_i t^i + * \f] + * where \f$d\f$ is the degree of the polynomial and \f$t\f$ is a scalar. + * The coefficients \f$x_i\f$, \f$i=0,\dots,d\f$ can be scalars, vectors, + * operators, etc., any type that can implement Teuchos::PolynomialTraits. + * A template specialization of Teuchos::PolynomialTraits must be provided + * for the coefficient type, however Teuchos::PolynomailTraits does provide + * a default template definition for scalars. + * + * This class provides methods for creating a polynomial of some degree, + * setting and retreiving coefficients, and evaluating the polynomial and + * its derivative at some value \f$t\f$. + */ + template + class Polynomial : virtual public Teuchos::Describable { + public: + + //! Typename of coefficients + typedef CoeffT coeff_type; + + //! Typename of scalars + typedef typename Teuchos::PolynomialTraits::scalar_type scalar_type; + + //! Create a polynomial of degree \c deg + /*! + * If \c reserve > \c deg, a polynomial of degree \c deg will be created, + * but space for \c reserve + 1 coefficients will be created to allow + * future increases in the degree of the polynomial to be more efficient. + * A clone of \c cloneCoeff will be placed at each coefficient. + */ + Polynomial(unsigned int deg, const CoeffT& cloneCoeff, + unsigned int reserve = 0); + + //! Create a polynomial of degree \c deg without cloning. DANGEROUS! + /*! + * In this version of the constructor, no clone object is provided, + * and therefore no storage will be created for each coefficient. + * In this case, setCoefficientPtr() below should be used to set + * each coefficient pointer to a valid cofficient. This constructor exists + * to be able to create an efficient "view" of another polynomial. + */ + Polynomial(unsigned int deg, unsigned int reserve = 0); + + //! Destructor + ~Polynomial(); + + //! Return degree of polynomial + unsigned int degree() const { return d; } + + //! Set degree of polynomial to \c deg + void setDegree(unsigned int deg); + + //! Return ref-count pointer to coefficient \c i + Teuchos::RCP + getCoefficient(unsigned int i); + + //! Return ref-count pointer to constant coefficient \c i + Teuchos::RCP + getCoefficient(unsigned int i) const; + + //! Set coefficient \c i to \c c + void setCoefficient(unsigned int i, const CoeffT& v); + + //! Set pointer for coefficient \c i to \c c_ptr. DANGEROUS! + /*! + * Directly set the coefficient pointer to c_ptr. This method should + * be used with care since future calls to setCoefficient(i,c) will + * also modify the coefficient pointed to \c c_ptr. However, in certain + * situations it is necessary to do this for efficiency. + */ + void setCoefficientPtr(unsigned int i, + const Teuchos::RCP& c_ptr); + + //! Evaluate polynomial and possibly its derivative at time \c t + /*! + * The value of the polynomial at \c t is computed and stored in \c *x. + * If \c xdot is not \c NULL, the derivative with respect to t is + * evaluated and stored in \c *xdot. + * + * Horner's method is used to efficiently evaluate the polynomial + * and its derivative. + */ + void evaluate(typename Teuchos::Polynomial::scalar_type t, + CoeffT* x, CoeffT* xdot = NULL) const; + + private: + + //! Prohibit copying + Polynomial(const Polynomial&); + + //! Prohibit copying + Polynomial& operator=(const Polynomial&); + + protected: + + //! Degree of polynomial + unsigned int d; + + //! Size of polynomial (may be > d) + unsigned int sz; + + //! Vector of polynomial coefficients + /*! + * \c coeff[i] corresponds to the degree \c i term, \c i=0,...,d + */ + std::vector< Teuchos::RCP > coeff; + + }; // class Polynomial + +} // end namespace Teuchos + +#endif // TEUCHOS_POLYNOMIAL_DECL_HPP diff --git a/fastlib/trilinos/include/Teuchos_PolynomialTraits.hpp b/fastlib/trilinos/include/Teuchos_PolynomialTraits.hpp new file mode 100644 index 0000000000..321287faa4 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_PolynomialTraits.hpp @@ -0,0 +1,79 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_POLYNOMIAL_TRAITS_HPP +#define TEUCHOS_POLYNOMIAL_TRAITS_HPP + +#include "Teuchos_RCP.hpp" + +namespace Teuchos { + + //! Traits class for polynomial coefficients in Teuchos::Polynomial. + /*! + * This class provides traits for implementing Teuchos::Polynomial. The + * default template definition here will work for any scalar type. Any other + * coefficient type for Teuchos::Polynomial should provide a specialization + * of this traits class for that type that mirrors the default definition + * below. + */ + template + class PolynomialTraits { + public: + + //! Typename of coefficients + typedef Scalar coeff_type; + + //! Typename of scalars + typedef Scalar scalar_type; + + //! Clone a coefficient + static inline Teuchos::RCP clone(const coeff_type& c) { + return Teuchos::rcp(new coeff_type(c)); + } + + //! Copy a coefficient + static inline void copy(const coeff_type& x, coeff_type* y) { + *y = x; + } + + //! Assign a scalar to a coefficient + static inline void assign(coeff_type* y, const scalar_type& alpha) { + *y = alpha; + } + + //! y = x + beta*y + static inline void update(coeff_type* y, const coeff_type& x, + const scalar_type& beta) { + *y = x + beta*(*y); + } + + }; // class PolynomialTraits + +} // end namespace Teuchos + +#endif // TEUCHOS_POLYNOMIAL_TRAITS_HPP diff --git a/fastlib/trilinos/include/Teuchos_PrimitiveTypeTraits.hpp b/fastlib/trilinos/include/Teuchos_PrimitiveTypeTraits.hpp new file mode 100644 index 0000000000..06fd30ba51 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_PrimitiveTypeTraits.hpp @@ -0,0 +1,172 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// //////////////////////////////////////////////////////////////////////// +// Teuchos_PrimitiveTypeTraits.hpp + +#ifndef TEUCHOS_PRIMITIVE_TYPE_TRAITS_H +#define TEUCHOS_PRIMITIVE_TYPE_TRAITS_H + +#include "Teuchos_TestForException.hpp" +#ifdef HAVE_TEUCHOS_GNU_MP +#include "gmp.h" +#include "gmpxx.h" +#endif + +/** \file Teuchos_PrimitiveTypeTraits.hpp + \brief Declaration of a templated traits class for decomposing an + object into an array of primitive objects + */ + +namespace Teuchos { + +/** \brief A templated traits class for decomposing object into an + * array of primitive objects. + * + * The idea behind this traits class it that it allows an object of + * semi-std::complex structure to be externalized into an array of + * primitive data types. + * + * This default traits class works just fine for types that are + * already primitive. + */ +template class PrimitiveTypeTraits { +public: + /** \brief . */ + typedef T primitiveType; + /** \brief . */ + static int numPrimitiveObjs() { return 1; } + /** \brief . */ + static void extractPrimitiveObjs( + const T &obj + ,const int numPrimitiveObjs + ,primitiveType primitiveObjs[] + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( numPrimitiveObjs!=1 || primitiveObjs==NULL, std::invalid_argument, "Error!" ); +#endif + primitiveObjs[0] = obj; + } + /** \brief . */ + static void loadPrimitiveObjs( + const int numPrimitiveObjs + ,const primitiveType primitiveObjs[] + ,T *obj + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( numPrimitiveObjs!=1 || primitiveObjs==NULL, std::invalid_argument, "Error!" ); +#endif + *obj = primitiveObjs[0]; + } +}; + +#if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX) + +/** \brief Partial specialization of PrimitiveTypeTraits for std::complex. + */ +template class PrimitiveTypeTraits< std::complex > { +public: + /** \brief . */ + typedef T primitiveType; + /** \brief . */ + static int numPrimitiveObjs() { return 2; } + /** \brief . */ + static void extractPrimitiveObjs( + const std::complex &obj + ,const int numPrimitiveObjs + ,primitiveType primitiveObjs[] + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( numPrimitiveObjs!=2 || primitiveObjs==NULL, std::invalid_argument, "Error!" ); +#endif + primitiveObjs[0] = obj.real(); + primitiveObjs[1] = obj.imag(); + } + /** \brief . */ + static void loadPrimitiveObjs( + const int numPrimitiveObjs + ,const primitiveType primitiveObjs[] + ,std::complex *obj + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( numPrimitiveObjs!=2 || primitiveObjs==NULL, std::invalid_argument, "Error!" ); +#endif + *obj = std::complex( primitiveObjs[0], primitiveObjs[1] ); + } +}; + +#endif // defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX) + +#ifdef HAVE_TEUCHOS_GNU_MP + +/** \brief Full specialization of PrimitiveTypeTraits for mpf_class. + * + * Note: This class is not complete yet! + */ +template <> class PrimitiveTypeTraits { +public: + /** \brief . */ + typedef double primitiveType; // Just a guess! + /** \brief . */ + static int numPrimitiveObjs() { return 10; } // Just a guess! + /** \brief . */ + static void extractPrimitiveObjs( + const mpf_class &obj + ,const int numPrimitiveObjs + ,primitiveType primitiveObjs[] + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( numPrimitiveObjs!=10 || primitiveObjs==NULL, std::invalid_argument, "Error!" ); +#endif + TEST_FOR_EXCEPT(true); // ToDo: Implement + } + /** \brief . */ + static void loadPrimitiveObjs( + const int numPrimitiveObjs + ,const primitiveType primitiveObjs[] + ,mpf_class *obj + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( numPrimitiveObjs!=10 || primitiveObjs==NULL, std::invalid_argument, "Error!" ); +#endif + TEST_FOR_EXCEPT(true); // ToDo: Implement + } +}; + +#endif // HAVE_TEUCHOS_GNU_MP + + +} // namespace Teuchos + +#endif // TEUCHOS_PRIMITIVE_TYPE_TRAITS_H diff --git a/fastlib/trilinos/include/Teuchos_PromotionTraits.hpp b/fastlib/trilinos/include/Teuchos_PromotionTraits.hpp new file mode 100644 index 0000000000..5abc2924ef --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_PromotionTraits.hpp @@ -0,0 +1,76 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef _TEUCHOS_PROMOTION_TRAITS_HPP_ +#define _TEUCHOS_PROMOTION_TRAITS_HPP_ + +#include "Teuchos_ConfigDefs.hpp" + +namespace Teuchos { + +template +class PromotionTraits +{ +public: +}; + +//Specialization +template class PromotionTraits { +public: + typedef T promote; +}; + +#define PT_SPEC(type1,type2,type3) \ +template <> class PromotionTraits< type1 , type2 > { \ +public: \ + typedef type3 promote; \ +}; \ +template <> class PromotionTraits< type2 , type1 > { \ +public: \ + typedef type3 promote; \ +}; + +#if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX) +PT_SPEC(double,std::complex,std::complex) +PT_SPEC(float,std::complex,std::complex) +PT_SPEC(float,std::complex,std::complex) +PT_SPEC(double,std::complex,std::complex) +#endif +PT_SPEC(double,float,double) +PT_SPEC(double,long,double) +PT_SPEC(double,int,double) +PT_SPEC(float,long,float) +PT_SPEC(float,int,float) + +// ToDo: Add specializations for extended precision types! + +#undef PT_SPEC + +} // Teuchos namespace + +#endif // _TEUCHOS_PROMOTION_TRAITS_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_RCP.hpp b/fastlib/trilinos/include/Teuchos_RCP.hpp new file mode 100644 index 0000000000..9bfa9b6bcc --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_RCP.hpp @@ -0,0 +1,602 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_RCP_HPP +#define TEUCHOS_RCP_HPP + +/*! \file Teuchos_RCP.hpp + \brief Reference-counted pointer class and non-member templated function implementations. +*/ +/** \example example/RCP/cxx_main.cpp + This is an example of how to use the Teuchos::RCP class. +*/ +/** \example test/RCP/cxx_main.cpp + This is a more detailed testing program that uses all of the Teuchos::RCP class. +*/ + +#include "Teuchos_RCPDecl.hpp" +#include "Teuchos_TestForException.hpp" +#include "Teuchos_dyn_cast.hpp" +#include "Teuchos_map.hpp" +#include "Teuchos_TypeNameTraits.hpp" + +//#define TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES // Define this on command line to keep track of this! + +// ///////////////////////////////////////////////////////////////////////// +// Inline implementations below, not for the client to look at. + +namespace Teuchos { + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + +namespace PrivateUtilityPack { + +// +class RCP_node; + +// Assert that the pointer is not null +void throw_null( const std::string &type_name ); + +// Node class to keep track of the delete address and +// the reference count for RCP<...> +class RCP_node { +public: + RCP_node(bool has_ownership) + : count_(1), has_ownership_(has_ownership), extra_data_map_(NULL) + {} + virtual ~RCP_node() + { + if(extra_data_map_) delete extra_data_map_; + } + int count() const { + return count_; + } + int incr_count() { + return ++count_; + } + int deincr_count() { + return --count_; + } + void has_ownership(bool has_ownership) { + has_ownership_ = has_ownership; + } + bool has_ownership() const { + return has_ownership_; + } + void set_extra_data( const any &extra_data, const std::string& name, EPrePostDestruction destroy_when, bool force_unique ); + any& get_extra_data( const std::string& type_name, const std::string& name ); + const any& get_extra_data( const std::string& type_name, const std::string& name ) const { + return const_cast(this)->get_extra_data(type_name,name); + } + any* get_optional_extra_data( const std::string& type_name, const std::string& name ); + const any* get_optional_extra_data( const std::string& type_name, const std::string& name ) const { + return const_cast(this)->get_optional_extra_data(type_name,name); + } +protected: + void pre_delete_extra_data() { + if(extra_data_map_) impl_pre_delete_extra_data(); + } +private: + struct extra_data_entry_t { + extra_data_entry_t() : destroy_when(POST_DESTROY) {} + extra_data_entry_t( const any &_extra_data, EPrePostDestruction _destroy_when ) + : extra_data(_extra_data), destroy_when(_destroy_when) {} + any extra_data; + EPrePostDestruction destroy_when; + }; + typedef Teuchos::map extra_data_map_t; + int count_; + bool has_ownership_; + extra_data_map_t *extra_data_map_; + // Above is made a pointer to reduce overhead for the general case + // where this is not used + void impl_pre_delete_extra_data(); + // Not defined and not to be called + RCP_node(); + RCP_node(const RCP_node&); + RCP_node& operator=(const RCP_node&); +}; // end class RCP_node; + +// Implementation class for actually deleting the object if has_ownership() == true. +template +class RCP_node_tmpl : public RCP_node { +public: + + // + RCP_node_tmpl(T* p, Dealloc_T dealloc, bool has_ownership) + : RCP_node(has_ownership), ptr_(p), dealloc_(dealloc) + {} + // + Dealloc_T& get_dealloc() { return dealloc_; } + // + const Dealloc_T& get_dealloc() const { return dealloc_; } + // + ~RCP_node_tmpl() { + this->pre_delete_extra_data(); + if( has_ownership() ) + dealloc_.free(ptr_); + } + +private: + + T *ptr_; + Dealloc_T dealloc_; + // not defined and not to be called + RCP_node_tmpl(); + RCP_node_tmpl(const RCP_node_tmpl&); + RCP_node_tmpl& operator=(const RCP_node_tmpl&); + +}; // end class RCP_node_tmpl + +// Add new RCP to global list +void add_new_RCP_node( RCP_node* rcp_node, const std::string &info ); + +// Remove RCP from global list +void remove_RCP_node( RCP_node* rcp_node ); + +// Print global list on destruction +class PrintActiveRCPNodes { +public: + PrintActiveRCPNodes(); + ~PrintActiveRCPNodes(); + void foo(); +private: + static int count_; +}; + +} // end namespace PrivateUtilityPack + +} // namespace Teuchos + +namespace { +// This static variable should be delcared before all other static variables +// that depend on RCP and therefore This static varaible should be +// deleted *after* all of these other static variables that depend on +// RCP go away! +Teuchos::PrivateUtilityPack::PrintActiveRCPNodes printActiveRCPNodes; +} // namespace + +#endif // DOXYGEN_SHOULD_SKIP_THIS + + +namespace Teuchos { + + +// ///////////////////////////////////////////////////////////////////////////////// +// Inline member functions for RCP<...>. + +template +inline +RCP::RCP( ENull ) + : ptr_(NULL) + , node_(NULL) +{} + +template +REFCOUNTPTR_INLINE +RCP::RCP(const RCP& r_ptr) + : ptr_(r_ptr.ptr_), node_(r_ptr.node_) +{ + if(node_) node_->incr_count(); +} + +template +REFCOUNTPTR_INLINE +template +RCP::RCP(const RCP& r_ptr) + : ptr_(const_cast(r_ptr.get())) // will not compile if T1 is not an ancestor of T2 + , node_(const_cast(r_ptr.access_node())) +{ + if(node_) node_->incr_count(); +} + +template +REFCOUNTPTR_INLINE +RCP::~RCP() +{ + if(node_ && node_->deincr_count() == 0 ) { +#ifdef TEUCHOS_DEBUG + printActiveRCPNodes.foo(); // Make sure this object is used! + remove_RCP_node(node_); +#endif + delete node_; + } +} + +template +REFCOUNTPTR_INLINE +RCP& RCP::operator=(const RCP& r_ptr) +{ + if( this == &r_ptr ) + return *this; // Assignment to self + if( node_ && !node_->deincr_count() ) { +#ifdef TEUCHOS_DEBUG + remove_RCP_node(node_); +#endif + delete node_; + } + ptr_ = r_ptr.ptr_; + node_ = r_ptr.node_; + if(node_) node_->incr_count(); + return *this; +} + +template +inline +T* RCP::operator->() const { +#ifdef TEUCHOS_REFCOUNTPTR_ASSERT_NONNULL + assert_not_null(); +#endif + return ptr_; +} + +template +inline +T& RCP::operator*() const { +#ifdef TEUCHOS_REFCOUNTPTR_ASSERT_NONNULL + assert_not_null(); +#endif + return *ptr_; +} + +template +inline +T* RCP::get() const { + return ptr_; +} + +template +REFCOUNTPTR_INLINE +T* RCP::release() { + if(node_) + node_->has_ownership(false); + return ptr_; +} + +template +REFCOUNTPTR_INLINE +int RCP::count() const { + if(node_) + return node_->count(); + return 0; +} + +template +REFCOUNTPTR_INLINE +void RCP::set_has_ownership() { + if(node_) + node_->has_ownership(true); +} + +template +REFCOUNTPTR_INLINE +bool RCP::has_ownership() const { + if(node_) + return node_->has_ownership(); + return false; +} + +template +REFCOUNTPTR_INLINE +template +bool RCP::shares_resource(const RCP& r_ptr) const { + return node_ == r_ptr.access_node(); + // Note: above, r_ptr is *not* the same class type as *this so we can not + // access its node_ member directly! This is an interesting detail to the + // C++ protected/private protection mechanism! +} + +template +inline +const RCP& RCP::assert_not_null() const { + if(!ptr_) PrivateUtilityPack::throw_null(TypeNameTraits::name()); + return *this; +} + +// very bad public functions + +template +inline +RCP::RCP( T* p, bool has_ownership ) + : ptr_(p) + , node_( p ? new PrivateUtilityPack::RCP_node_tmpl >(p,DeallocDelete(),has_ownership) : NULL ) +{ +#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES + if(node_) { + std::ostringstream os; + os << "{T=\'"<::name()<<"\',Concrete T=\'"< +REFCOUNTPTR_INLINE +template +RCP::RCP( T* p, Dealloc_T dealloc, bool has_ownership ) + : ptr_(p) + , node_( p ? new PrivateUtilityPack::RCP_node_tmpl(p,dealloc,has_ownership) : NULL ) +{ +#ifdef TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODES + if(node_) { + std::ostringstream os; + os << "{T=\'"<::name()<<"\',Concrete T=\'"< +inline +RCP::RCP( T* p, node_t* node) + : ptr_(p), node_(node) +{ + if(node_) node_->incr_count(); +} + +template +inline +T*& RCP::access_ptr() +{ return ptr_; } + +template +inline +typename RCP::node_t*& RCP::access_node() +{ return node_; } + +template +inline +typename RCP::node_t* RCP::access_node() const +{ return node_; } + +} // end namespace Teuchos + +// ///////////////////////////////////////////////////////////////////////////////// +// Inline non-member functions for RCP + +template +inline +Teuchos::RCP +Teuchos::rcp( T* p, bool owns_mem ) +{ + return RCP(p,owns_mem); +} + +template +inline +Teuchos::RCP +Teuchos::rcp( T* p, Dealloc_T dealloc, bool owns_mem ) +{ + return RCP(p,dealloc,owns_mem); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::is_null( const RCP &p ) +{ + return p.get() == NULL; +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator==( const RCP &p, ENull ) +{ + return p.get() == NULL; +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator!=( const RCP &p, ENull ) +{ + return p.get() != NULL; +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator==( const RCP &p1, const RCP &p2 ) +{ + return p1.access_node() == p2.access_node(); +} + +template +REFCOUNTPTR_INLINE +bool Teuchos::operator!=( const RCP &p1, const RCP &p2 ) +{ + return p1.access_node() != p2.access_node(); +} + +template +REFCOUNTPTR_INLINE +Teuchos::RCP +Teuchos::rcp_implicit_cast(const RCP& p1) +{ + T2 *check = p1.get(); // Make the compiler check if the conversion is legal + RCP p2; + if(p1.access_node()) { + p2.access_ptr() = check; + p2.access_node() = const_cast&>(p1).access_node(); + p2.access_node()->incr_count(); + } + return p2; +} + +template +REFCOUNTPTR_INLINE +Teuchos::RCP +Teuchos::rcp_static_cast(const RCP& p1) +{ + T2 *check = static_cast(p1.get()); // Make the compiler check if the conversion is legal + RCP p2; + if(p1.access_node()) { + p2.access_ptr() = check; + p2.access_node() = const_cast&>(p1).access_node(); + p2.access_node()->incr_count(); + } + return p2; +} + +template +REFCOUNTPTR_INLINE +Teuchos::RCP +Teuchos::rcp_const_cast(const RCP& p1) +{ + T2 *check = const_cast(p1.get()); // Make the compiler check if the conversion is legal + RCP p2; + if(p1.access_node()) { + p2.access_ptr() = check; + p2.access_node() = const_cast&>(p1).access_node(); + p2.access_node()->incr_count(); + } + return p2; +} + +template +REFCOUNTPTR_INLINE +Teuchos::RCP +Teuchos::rcp_dynamic_cast(const RCP& p1, bool throw_on_fail) +{ + RCP p2; // NULL by default + if( p1.get() ) { + T2 *check = NULL; + if(throw_on_fail) + check = &dyn_cast(*p1); + else + check = dynamic_cast(p1.get()); // Make the compiler check if the conversion is legal + if(check) { + p2.access_ptr() = check; + p2.access_node() = const_cast&>(p1).access_node(); + p2.access_node()->incr_count(); + } + } + return p2; +} + +template +REFCOUNTPTR_INLINE +void Teuchos::set_extra_data( const T1 &extra_data, const std::string& name, Teuchos::RCP *p, EPrePostDestruction destroy_when, bool force_unique ) +{ + p->assert_not_null(); + p->access_node()->set_extra_data( any(extra_data), name, destroy_when, force_unique ); +} + +template +REFCOUNTPTR_INLINE +T1& Teuchos::get_extra_data( RCP& p, const std::string& name ) +{ + p.assert_not_null(); + return any_cast(p.access_node()->get_extra_data(TypeNameTraits::name(),name)); +} + +template +REFCOUNTPTR_INLINE +const T1& Teuchos::get_extra_data( const RCP& p, const std::string& name ) +{ + p.assert_not_null(); + return any_cast(p.access_node()->get_extra_data(TypeNameTraits::name(),name)); +} + +template +REFCOUNTPTR_INLINE +T1* Teuchos::get_optional_extra_data( RCP& p, const std::string& name ) +{ + p.assert_not_null(); + any *extra_data = p.access_node()->get_optional_extra_data(TypeNameTraits::name(),name); + if( extra_data ) return &any_cast(*extra_data); + return NULL; +} + +template +REFCOUNTPTR_INLINE +const T1* Teuchos::get_optional_extra_data( const RCP& p, const std::string& name ) +{ + p.assert_not_null(); + any *extra_data = p.access_node()->get_optional_extra_data(TypeNameTraits::name(),name); + if( extra_data ) return &any_cast(*extra_data); + return NULL; +} + +template +REFCOUNTPTR_INLINE +Dealloc_T& +Teuchos::get_dealloc( RCP& p ) +{ + typedef PrivateUtilityPack::RCP_node_tmpl requested_type; + p.assert_not_null(); + PrivateUtilityPack::RCP_node_tmpl + *dnode = dynamic_cast*>(p.access_node()); + TEST_FOR_EXCEPTION( + dnode==NULL, std::logic_error + ,"get_dealloc<" << TypeNameTraits::name() << "," << TypeNameTraits::name() << ">(p): " + << "Error, requested type \'" << TypeNameTraits::name() + << "\' does not match actual type of the node \'" << typeName(*p.access_node()) << "!" + ); + return dnode->get_dealloc(); +} + +template +inline +const Dealloc_T& +Teuchos::get_dealloc( const Teuchos::RCP& p ) +{ + return get_dealloc(const_cast&>(p)); +} + +template +REFCOUNTPTR_INLINE +Dealloc_T* +Teuchos::get_optional_dealloc( RCP& p ) +{ + p.assert_not_null(); + PrivateUtilityPack::RCP_node_tmpl + *dnode = dynamic_cast*>(p.access_node()); + if(dnode) + return &dnode->get_dealloc(); + return NULL; +} + +template +inline +const Dealloc_T* +Teuchos::get_optional_dealloc( const Teuchos::RCP& p ) +{ + return get_optional_dealloc(const_cast&>(p)); +} + +template +std::ostream& Teuchos::operator<<( std::ostream& out, const RCP& p ) +{ + out + << TypeNameTraits >::name() << "{" + << "ptr="<<(const void*)(p.get()) // I can't find any alternative to this C cast :-( + <<",node="< +Teuchos::RCP +Teuchos::rcp( const boost::shared_ptr &sptr ) +{ + if(sptr.get()) { + const RCPDeleter + *rcpd = boost::get_deleter >(sptr); + if(rcpd) + return rcpd->ptr(); + return rcp(sptr.get(),DeallocBoostSharedPtr(sptr),true); + } + return null; +} + +template +boost::shared_ptr +Teuchos::shared_pointer( const RCP &rcp ) +{ + if(rcp.get()) { + const DeallocBoostSharedPtr + *dbsp = get_optional_dealloc >(rcp); + if(dbsp) + return dbsp->ptr(); + return boost::shared_ptr(rcp.get(),RCPDeleter(rcp)); + } + return boost::shared_ptr(); +} + +#endif // TEUCHOS_RCP_SHAREDPTR_CONVERSIONS_HPP diff --git a/fastlib/trilinos/include/Teuchos_RCPBoostSharedPtrConversionsDecl.hpp b/fastlib/trilinos/include/Teuchos_RCPBoostSharedPtrConversionsDecl.hpp new file mode 100644 index 0000000000..e2c5403d82 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_RCPBoostSharedPtrConversionsDecl.hpp @@ -0,0 +1,121 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_RCP_SHAREDPTR_CONVERSIONS_DECL_HPP +#define TEUCHOS_RCP_SHAREDPTR_CONVERSIONS_DECL_HPP + +#include "Teuchos_RCPDecl.hpp" +#include "boost/shared_ptr.hpp" + +namespace Teuchos { + +/** \defgroup Teuchos_RCPBoostSharedPtrConversions_grp Conversion utilities for going between Teuchos::RCP and boost::shared_ptr. + +The smart pointer classes Teuchos::RCP and +boost::shared_ptr are easily compatible. The two templated +conversion functions Teuchos::rcp( const boost::shared_ptr & ) and +Teuchos::shared_pointer( const RCP & ) have been created +for converting back and forth. + +The following code shows how to convert back and forth between these two smart +pointer types: + +\ingroup teuchos_mem_mng_grp + +*/ +//@{ + +/** \brief Teuchos::RCP Deallocator class that wraps a + * boost::shared_ptr */ +template +class DeallocBoostSharedPtr +{ +public: + /** \brief. */ + DeallocBoostSharedPtr( const boost::shared_ptr &sptr ) : sptr_(sptr) {} + /** \brief. */ + typedef T ptr_t; + /** \brief. */ + void free( T* ptr ) const { sptr_.reset(); } + /** \brief. */ + const boost::shared_ptr& ptr() const { return sptr_; } +private: + mutable boost::shared_ptr sptr_; + DeallocBoostSharedPtr(); // Not defined and not to be called! +}; + +/** \brief boost::shared_ptr deleter class that wraps a + * Teuchos::RCP. + */ +template +class RCPDeleter +{ +public: + /** \brief. */ + RCPDeleter( const RCP &rcp ) : rcp_(rcp) {} + /** \brief. */ + typedef void result_type; + /** \brief. */ + typedef T * argument_type; + /** \brief. */ + void operator()(T * x) const { rcp_ = null; } + /** \brief. */ + const RCP& ptr() const { return rcp_; } +private: + mutable RCP rcp_; + RCPDeleter(); // Not defined and not to be called! +}; + +/** \brief Conversion function that takes in a boost::shared_ptr + * object and spits out a Teuchos::RCP object. + * + * If the input boost::shared_ptr already wraps a Teuchos::RCP + * object, then that Teuchos::RCP object will be copied and returned. + * + * This function is not complicated, just look at its defintion below. + */ +template +RCP rcp( const boost::shared_ptr &sptr ); + +/** \brief Conversion function that takes in a Teuchos::RCP + * object and spits out a boost::shared_ptr object. + * + * If the input Teuchos::RCP already wraps a + * boost::shared_ptr object, then that boost::shared_ptr + * object will be copied and returned. + * + * This function is not complicated, just look at its defintion below. + */ +template +boost::shared_ptr shared_pointer( const RCP &rcp ); + +//@} + +} // namespace Teuchos + +#endif // TEUCHOS_RCP_SHAREDPTR_CONVERSIONS_DECL_HPP diff --git a/fastlib/trilinos/include/Teuchos_RCPDecl.hpp b/fastlib/trilinos/include/Teuchos_RCPDecl.hpp new file mode 100644 index 0000000000..fd312f019a --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_RCPDecl.hpp @@ -0,0 +1,1184 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_RCP_DECL_HPP +#define TEUCHOS_RCP_DECL_HPP + +/*! \file Teuchos_RCPDecl.hpp + \brief Reference-counted pointer class and non-member templated function implementations. +*/ + +#include "Teuchos_any.hpp" + +#ifdef REFCOUNTPTR_INLINE_FUNCS +# define REFCOUNTPTR_INLINE inline +#else +# define REFCOUNTPTR_INLINE +#endif + +#ifdef TEUCHOS_DEBUG +# define TEUCHOS_REFCOUNTPTR_ASSERT_NONNULL +#endif + +namespace Teuchos { + +namespace PrivateUtilityPack { + class RCP_node; +} + +/** \brief Used to initialize a RCP object to NULL using an + * implicit conversion! + * + * \relates RCP + */ +enum ENull { null }; + +/** \brief Used to specify a pre or post destruction of extra data + * + * \relates RCP + */ +enum EPrePostDestruction { PRE_DESTROY, POST_DESTROY }; + +/** \brief Smart reference counting pointer class for automatic garbage + collection. + +For a carefully written discussion about what this class is and basic +details on how to use it see the +beginners guide. + +Quickstart for RCP + +Here we present a short, but fairly comprehensive, quick-start for the +use of RCP<>. The use cases described here +should cover the overwhelming majority of the use instances of +RCP<> in a typical program. + +The following class hierarchy will be used in the C++ examples given +below. + +\code + +class A { public: virtual ~A(){} virtual void f(){} }; +class B1 : virtual public A {}; +class B2 : virtual public A {}; +class C : virtual public B1, virtual public B2 {}; + +class D {}; +class E : public D {}; + +\endcode + +All of the following code examples used in this quickstart are assumed to be +in the namespace Teuchos or have appropriate using +Teuchos::... declarations. This removes the need to explicitly use +Teuchos:: to qualify classes, functions and other declarations from +the Teuchos namespace. Note that some of the runtime checks are +denoted as "debug runtime checked" which means that checking will only be +performed in a debug build (that is one where the macro +TEUCHOS_REFCOUNTPTR_ASSERT_NONNULL, or TEUCHOS_DEBUG is defined at compile time). + +
      + +
    1. Creation of RCP<> objects + +
        + +
      1. Creating a RCP<> object using new + +\code +RCP c_ptr = rcp(new C); +\endcode + +
      2. Creating a RCP<> object to an array allocated using new[n] : Teuchos::DeallocArrayDelete + +\code + +RCP c_ptr = rcp(new C[n],DeallocArrayDelete(),true); +\endcode + +
      3. Creating a RCP<> object equipped with a specialized deallocator function : Teuchos::DeallocFunctorDelete + +\code + +void someDeallocFunction(C* c_ptr); + +RCP c_ptr = rcp(new deallocFunctorDelete(someDeallocFunction),true); +\endcode + +
      4. Initializing a RCP<> object to NULL + +\code +RCP c_ptr; +\endcode +or +\code +RCP c_ptr = null; +\endcode + +
      5. Initializing a RCP<> object to an object + \underline{not} allocated with new + +\code +C c; +RCP c_ptr = rcp(&c,false); +\endcode + +
      6. Copy constructor (implicit casting) + +\code +RCP c_ptr = rcp(new C); // No cast +RCP a_ptr = c_ptr; // Cast to base class +RCP ca_ptr = a_ptr; // Cast from non-const to const +\endcode + +
      7. Representing constantness and non-constantness + +
          + +
        1. Non-constant pointer to non-constant object +\code +RCP c_ptr; +\endcode + +
        2. Constant pointer to non-constant object +\code +const RCP c_ptr; +\endcode + +
        3. Non-Constant pointer to constant object +\code +RCP c_ptr; +\endcode + +
        4. Constant pointer to constant object +\code +const RCP c_ptr; +\endcode + +
        + +
      + +
    2. Reinitialization of RCP<> objects (using assignment operator) + +
        + +
      1. Resetting from a raw pointer + +\code +RCP a_ptr; +a_ptr = rcp(new C()); +\endcode + +
      2. Resetting to null + +\code +RCP a_ptr = rcp(new C()); +a_ptr = null; // The C object will be deleted here +\endcode + +
      3. Assigning from a RCP<> object + +\code +RCP a_ptr1; +RCP a_ptr2 = rcp(new C()); +a_ptr1 = a_ptr2; // Now a_ptr1 and a_ptr2 point to same C object +\endcode + +
      + +
    3. Accessing the reference-counted object + +
        + +
      1. Access to object reference (debug runtime checked) : Teuchos::RCP::operator*() + +\code +C &c_ref = *c_ptr; +\endcode + +
      2. Access to object pointer (unchecked, may return NULL) : Teuchos::RCP::get() + +\code +C *c_rptr = c_ptr.get(); +\endcode + +
      3. Access to object pointer (debug runtime checked, will not return NULL) : Teuchos::RCP::operator*() + +\code +C *c_rptr = &*c_ptr; +\endcode + +
      4. Access of object's member (debug runtime checked) : Teuchos::RCP::operator->() + +\code +c_ptr->f(); +\endcode + +
      5. Testing for non-null : Teuchos::RCP::get(), Teuchos::operator==(), Teuchos::operator!=() + +\code +if( a_ptr.get() ) std::cout << "a_ptr is not null!\n"; +\endcode + +or + +\code +if( a_ptr != null ) std::cout << "a_ptr is not null!\n"; +\endcode + +or + +
      6. Testing for null + +\code +if( !a_ptr.get() ) std::cout << "a_ptr is null!\n"; +\endcode + +or + +\code +if( a_ptr == null ) std::cout << "a_ptr is null!\n"; +\endcode + +or + +\code +if( is_null(a_ptr) ) std::cout << "a_ptr is null!\n"; +\endcode + +
      + +
    4. Casting + +
        + +
      1. Implicit casting (see copy constructor above) + +
          + +
        1. Using copy constructor (see above) + +
        2. Using conversion function + +\code +RCP c_ptr = rcp(new C); // No cast +RCP a_ptr = rcp_implicit_cast(c_ptr); // To base +RCP ca_ptr = rcp_implicit_cast(a_ptr);// To const +\endcode + +
        + +
      2. Casting away const : rcp_const_cast() + +\code +RCP ca_ptr = rcp(new C); +RCP a_ptr = rcp_const_cast(ca_ptr); // cast away const! +\endcode + +
      3. Static cast (no runtime check) : rcp_static_cast() + +\code +RCP d_ptr = rcp(new E); +RCP e_ptr = rcp_static_cast(d_ptr); // Unchecked, unsafe? +\endcode + +
      4. Dynamic cast (runtime checked, failed cast allowed) : rcp_dynamic_cast() + +\code +RCP a_ptr = rcp(new C); +RCP b1_ptr = rcp_dynamic_cast(a_ptr); // Checked, safe! +RCP b2_ptr = rcp_dynamic_cast(b1_ptr); // Checked, safe! +RCP c_ptr = rcp_dynamic_cast(b2_ptr); // Checked, safe! +\endcode + +
      5. Dynamic cast (runtime checked, failed cast not allowed) : rcp_dynamic_cast() + +\code +RCP a_ptr1 = rcp(new C); +RCP a_ptr2 = rcp(new A); +RCP b1_ptr1 = rcp_dynamic_cast(a_ptr1,true); // Success! +RCP b1_ptr2 = rcp_dynamic_cast(a_ptr2,true); // Throw std::bad_cast! +\endcode + +
      + + +
    5. Customized deallocators + +
        + +
      1. Creating a RCP<> object with a custom deallocator : Teuchos::DeallocArrayDelete + +\code +RCP c_ptr = rcp(new C[N],DeallocArrayDelete(),true); +\endcode + +
      2. Access customized deallocator (runtime checked, throws on failure) : Teuchos::get_dealloc() + +\code +const DeallocArrayDelete + &dealloc = get_dealloc >(c_ptr); +\endcode + +
      3. Access optional customized deallocator : Teuchos::get_optional_dealloc() + +\code +const DeallocArrayDelete + *dealloc = get_optional_dealloc >(c_ptr); +if(dealloc) std::cout << "This deallocator exits!\n"; +\endcode + +
      + +
    6. Managing extra data + +
        + +
      1. Adding extra data (post destruction of extra data) : Teuchos::set_extra_data() + +\code +set_extra_data(rcp(new B1),"A:B1",&a_ptr); +\endcode + +
      2. Adding extra data (pre destruction of extra data) : Teuchos::get_extra_data() + +\code +set_extra_data(rcp(new B1),"A:B1",&a_ptr,PRE_DESTORY); +\endcode + +
      3. Retrieving extra data : Teuchos::get_extra_data() + +\code +get_extra_data >(a_ptr,"A:B1")->f(); +\endcode + +
      4. Resetting extra data : Teuchos::get_extra_data() + +\code +get_extra_data >(a_ptr,"A:B1") = rcp(new C); +\endcode + +
      5. Retrieving optional extra data : Teuchos::get_optional_extra_data() + +\code +const RCP + *b1 = get_optional_extra_data >(a_ptr,"A:B1"); +if(b1) (*b1)->f(); +\endcode + +
      + +
    + +\ingroup teuchos_mem_mng_grp + + */ +template +class RCP { +public: + /** \brief . */ + typedef T element_type; + /** \brief Initialize RCP to NULL. + * + * This allows clients to write code like: + \code + RCP p = null; + \endcode + or + \code + RCP p; + \endcode + * and construct to NULL + */ + RCP( ENull null_arg = null ); + /** \brief Construct from a raw pointer. + * + * Note that this constructor is declared explicit so there is no implicit + * conversion from a raw pointer to an RCP allowed. If + * has_ownership==false, then no attempt to delete the object will + * occur. + * + * Postconditons:
      + *
    • this->get() == p + *
    • this->count() == 1 + *
    • this->has_ownership() == has_ownership + *
    + */ + explicit RCP( T* p, bool has_ownership = false ); + /** \brief Initialize from another RCP object. + * + * After construction, this and r_ptr will + * reference the same object. + * + * This form of the copy constructor is required even though the + * below more general templated version is sufficient since some + * compilers will generate this function automatically which will + * give an incorrect implementation. + * + * Postconditons:
      + *
    • this->get() == r_ptr.get() + *
    • this->count() == r_ptr.count() + *
    • this->has_ownership() == r_ptr.has_ownership() + *
    • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 + *
    + */ + RCP(const RCP& r_ptr); + /** \brief Initialize from another RCP object (implicit conversion only). + * + * This function allows the implicit conversion of smart pointer objects just + * like with raw C++ pointers. Note that this function will only compile + * if the statement T1 *ptr = r_ptr.get() will compile. + * + * Postconditons:
      + *
    • this->get() == r_ptr.get() + *
    • this->count() == r_ptr.count() + *
    • this->has_ownership() == r_ptr.has_ownership() + *
    • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 + *
    + */ + template + RCP(const RCP& r_ptr); + /** \brief Removes a reference to a dynamically allocated object and possibly deletes + * the object if owned. + * + * Deletes the object if this->has_ownership() == true and + * this->count() == 1. If this->count() == 1 but + * this->has_ownership() == false then the object is not deleted. + * If this->count() > 1 then the internal reference count shared by + * all the other related RCP<...> objects for this shared + * object is deincremented by one. If this->get() == NULL then + * nothing happens. + */ + ~RCP(); + /** \brief Copy the pointer to the referenced object and increment the + * reference count. + * + * If this->has_ownership() == true and this->count() == 1 + * before this operation is called, then the object pointed to by + * this->get() will be deleted (usually using delete) + * prior to binding to the pointer (possibly NULL) pointed to in + * r_ptr. Assignment to self (i.e. this->get() == + * r_ptr.get()) is harmless and this function does nothing. + * + * Postconditons:
      + *
    • this->get() == r_ptr.get() + *
    • this->count() == r_ptr.count() + *
    • this->has_ownership() == r_ptr.has_ownership() + *
    • If r_ptr.get() != NULL then r_ptr.count() is incremented by 1 + *
    + */ + RCP& operator=(const RCP& r_ptr); + /** \brief Pointer (->) access to members of underlying object. + * + * Preconditions:
      + *
    • this->get() != NULL (throws std::logic_error) + *
    + */ + T* operator->() const; + /** \brief Dereference the underlying object. + * + * Preconditions:
      + *
    • this->get() != NULL (throws std::logic_error) + *
    + */ + T& operator*() const; + /** \brief Get the raw C++ pointer to the underlying object. + */ + T* get() const; + /** \brief Release the ownership of the underlying dynamically allocated object. + * + * After this function is called then the client is responsible for + * deallocating the shared object no matter how many + * ref_count_prt objects have a reference to it. If + * this->get()== NULL, then this call is meaningless. + * + * Note that this function does not have the exact same semantics as does + * auto_ptr::release(). In auto_ptr::release(), + * this is set to NULL while here in RCP:: + * release() only an ownership flag is set and *this still points + * to the same object. It would be difficult to duplicate the behavior of + * auto_ptr::release() for this class. + * + * Postconditions: + *
      + *
    • this->has_ownership() == false + *
    + * + * @return Returns the value of this->get() + */ + T* release(); + /** \brief Return the number of RCP<> objects that have a reference + * to the underlying pointer that is being shared. + * + * @return If this->get() == NULL then this function returns 0. + * Otherwise, this function returns 0. + */ + int count() const; + /** \brief Give this and other RCP<> objects ownership + * of the referenced object this->get(). + * + * See ~RCP() above. This function + * does nothing if this->get() == NULL. + * + * Postconditions: + *
      + *
    • If this->get() == NULL then + *
        + *
      • this->has_ownership() == false (always!). + *
      + *
    • else + *
        + *
      • this->has_ownership() == true + *
      + *
    + */ + void set_has_ownership(); + /** \brief Returns true if this has ownership of object pointed to by this->get() in order to delete it. + * + * See ~RCP() above. + * + * @return If this->get() == NULL then this function always returns false. + * Otherwise the value returned from this function depends on which function was + * called most recently, if any; set_has_ownership() (true) + * or release() (false). + */ + bool has_ownership() const; + /** \brief Returns true if the smart pointers share the same underlying reference-counted object. + * + * This method does more than just check if this->get() == r_ptr.get(). + * It also checks to see if the underlying reference counting machinary is the + * same. + */ + template + bool shares_resource(const RCP& r_ptr) const; + /** \brief Throws std::logic_error if this->get()==NULL, otherwise returns reference to *this. */ + const RCP& assert_not_null() const; + +public: // Bad bad bad + + // ////////////////////////////////////// + // Private types + + typedef PrivateUtilityPack::RCP_node node_t; + +private: + + // ////////////////////////////////////////////////////////////// + // Private data members + + T *ptr_; // NULL if this pointer is null + node_t *node_; // NULL if this pointer is null + +public: // Bad bad bad +#ifndef DOXYGEN_COMPILE + // These constructors should be private but I have not had good luck making + // this portable (i.e. using friendship etc.) in the past + template + RCP( T* p, Dealloc_T dealloc, bool has_ownership ); + // This is a very bad breach of encapsulation that is needed since MS VC++ 5.0 will + // not allow me to declare template functions as friends. + RCP( T* p, node_t* node); + T*& access_ptr(); + node_t*& access_node(); + node_t* access_node() const; +#endif + +}; // end class RCP<...> + +/** \brief Traits specialization. + * + * \ingroup teuchos_mem_mng_grp + */ +template +class TypeNameTraits > { +public: + static std::string name() { return "RCP<"+TypeNameTraits::name()+">"; } +}; + + +/** \brief Policy class for deallocator that uses delete to delete a + * pointer which is used by RCP. + * + * \ingroup teuchos_mem_mng_grp + */ +template +class DeallocDelete +{ +public: + /// Gives the type (required) + typedef T ptr_t; + /// Deallocates a pointer ptr using delete ptr (required). + void free( T* ptr ) { if(ptr) delete ptr; } +}; + +/** \brief Deallocator class that uses delete [] to delete memory + * allocated uisng new [] + * + * \ingroup teuchos_mem_mng_grp + */ +template +class DeallocArrayDelete +{ +public: + /// Gives the type (required) + typedef T ptr_t; + /// Deallocates a pointer ptr using delete [] ptr (required). + void free( T* ptr ) { if(ptr) delete [] ptr; } +}; + +/** \brief Deallocator subclass that Allows any functor object (including a + * function pointer) to be used to free an object. + * + * Note, the only requirement is that deleteFuctor(ptr) can be called (which + * is true for a function pointer). + * + * Note, a client should generally use the function + * deallocFunctorDelete() to create this object and not try to + * construct it directly. + * + * \ingroup teuchos_mem_mng_grp + */ +template +class DeallocFunctorDelete +{ +public: + DeallocFunctorDelete( DeleteFunctor deleteFunctor ) : deleteFunctor_(deleteFunctor) {} + typedef T ptr_t; + void free( T* ptr ) { if(ptr) deleteFunctor_(ptr); } +private: + DeleteFunctor deleteFunctor_; + DeallocFunctorDelete(); // Not defined and not to be called! +}; + +/** \brief A simple function used to create a functor deallocator object. + * + * \relates DeallocFunctorDelete + */ +template +DeallocFunctorDelete +deallocFunctorDelete( DeleteFunctor deleteFunctor ) +{ + return DeallocFunctorDelete(deleteFunctor); +} + +/** \brief Deallocator subclass that Allows any functor object (including a + * function pointer) to be used to free a handle (i.e. pointer to pointer) to + * an object. + * + * Note, the only requirement is that deleteFuctor(ptrptr) can be called + * (which is true for a function pointer). + * + * Note, a client should generally use the function + * deallocFunctorDelete() to create this object and not try to + * construct it directly. + * + * \ingroup teuchos_mem_mng_grp + */ +template +class DeallocFunctorHandleDelete +{ +public: + DeallocFunctorHandleDelete( DeleteHandleFunctor deleteHandleFunctor ) + : deleteHandleFunctor_(deleteHandleFunctor) {} + typedef T ptr_t; + void free( T* ptr ) { if(ptr) { T **hdl = &ptr; deleteHandleFunctor_(hdl); } } +private: + DeleteHandleFunctor deleteHandleFunctor_; + DeallocFunctorHandleDelete(); // Not defined and not to be called! +}; + +/** \brief A simple function used to create a functor deallocator object. + * + * \relates DeallocFunctorHandleDelete + */ +template +DeallocFunctorHandleDelete +deallocFunctorHandleDelete( DeleteHandleFunctor deleteHandleFunctor ) +{ + return DeallocFunctorHandleDelete(deleteHandleFunctor); +} + +/** \brief Create a RCP object properly typed. + * + * @param p [in] Pointer to an object to be reference counted. + * @param owns_mem + * [in] If owns_mem==true then delete p + * will be called when the last reference to this object + * is removed. If owns_mem==false then nothing + * will happen to delete the the object pointed to by + * p when the last reference is removed. + * + * Preconditions:
      + *
    • If owns_mem==true then p must have been + * created by calling new to create the object since + * delete p will be called eventually. + *
    + * + * If the pointer p did not come from new then + * either the client should use the version of rcp() that + * that uses a deallocator policy object or should pass in + * owns_mem = false. + * + * \relates RCP + */ +template +RCP rcp( T* p, bool owns_mem +#ifndef __sun + = true +#endif + ); +#ifdef __sun // RAB: 20040303: Sun needs to fix their compiler +template inline RCP rcp( T* p ) { return rcp(p,true); } +#endif + +/** \brief Initialize from a raw pointer with a deallocation policy. + * + * @param p [in] Raw C++ pointer that \c this will represent. + * @param dealloc [in] Deallocator policy object (copied by value) that defines + * a function void Dealloc_T::free(T* p) that will + * free the underlying object. + * @param owns_mem + * [in] If true then return is allowed to delete + * the underlying pointer by calling dealloc.free(p). + * when all references have been removed. + * + * Preconditions:
      + *
    • The function void Dealloc_T::free(T* p) exists. + *
    + * + * Postconditions:
      + *
    • return.get() == p + *
    • If p == NULL then + *
        + *
      • return.count() == 0 + *
      • return.has_ownership() == false + *
      + *
    • else + *
        + *
      • return.count() == 1 + *
      • return.has_ownership() == owns_mem + *
      + *
    + * + * By default, return has ownership to delete the object + * pointed to by p when return is deleted (see + * ~RCP()). If owns_mem==true, it is vital + * that the address p + * passed in is the same address that was returned by new. + * With multiple inheritance this is not always the case. See the + * above discussion. This class is templated to accept a deallocator + * object that will free the pointer. The other functions use a + * default deallocator of type DeallocDelete which has a method + * DeallocDelete::free() which just calls delete p. + * + * \relates RCP + */ +template +RCP rcp( T* p, Dealloc_T dealloc, bool owns_mem ); + +/** \brief Returns true if p.get()==NULL. + * + * \relates RCP + */ +template +bool is_null( const RCP &p ); + +/** \brief Returns true if p.get()==NULL. + * + * \relates RCP + */ +template +bool operator==( const RCP &p, ENull ); + +/** \brief Returns true if p.get()!=NULL. + * + * \relates RCP + */ +template +bool operator!=( const RCP &p, ENull ); + +/** \brief Return true if two RCP objects point to the same + * referenced-counted object and have the same node. + * + * \relates RCP + */ +template +bool operator==( const RCP &p1, const RCP &p2 ); + +/** \brief Return true if two RCP objects do not point to the + * same referenced-counted object and have the same node. + * + * \relates RCP + */ +template +bool operator!=( const RCP &p1, const RCP &p2 ); + +/** \brief Implicit cast of underlying RCP type from T1* to T2*. + * + * The function will compile only if (T2* p2 = p1.get();) compiles. + * + * This is to be used for conversions up an inheritance hierarchy and from non-const to + * const and any other standard implicit pointer conversions allowed by C++. + * + * \relates RCP + */ +template +RCP rcp_implicit_cast(const RCP& p1); + +/** \brief Static cast of underlying RCP type from T1* to T2*. + * + * The function will compile only if (static_cast(p1.get());) compiles. + * + * This can safely be used for conversion down an inheritance hierarchy + * with polymorphic types only if dynamic_cast(p1.get()) == static_cast(p1.get()). + * If not then you have to use rcp_dynamic_cast(p1). + * + * \relates RCP + */ +template +RCP rcp_static_cast(const RCP& p1); + +/** \brief Constant cast of underlying RCP type from T1* to T2*. + * + * This function will compile only if (const_cast(p1.get());) compiles. + * + * \relates RCP + */ +template +RCP rcp_const_cast(const RCP& p1); + +/** \brief Dynamic cast of underlying RCP type from T1* to T2*. + * + * @param p1 [in] The smart pointer casting from + * @param throw_on_fail [in] If true then if the cast fails (for p1.get()!=NULL) then + * a std::bad_cast std::exception is thrown with a very informative + * error message. + * + * Postconditions:
      + *
    • If ( p1.get()!=NULL && throw_on_fail==true && dynamic_cast(p1.get())==NULL ) == true + * then an std::bad_cast std::exception is thrown with a very informative error message. + *
    • If ( p1.get()!=NULL && dynamic_cast(p1.get())!=NULL ) == true + * then return.get() == dynamic_cast(p1.get()). + *
    • If ( p1.get()!=NULL && throw_on_fail==false && dynamic_cast(p1.get())==NULL ) == true + * then return.get() == NULL. + *
    • If ( p1.get()==NULL ) == true + * then return.get() == NULL. + *
    + * + * This function will compile only if (dynamic_cast(p1.get());) compiles. + * + * \relates RCP + */ +template +RCP rcp_dynamic_cast( + const RCP& p1 + ,bool throw_on_fail +#ifndef __sun + = false +#endif + ); +#ifdef __sun // RAB: 20041019: Sun needs to fix their compiler +template inline RCP rcp_dynamic_cast( const RCP& p1 ) +{ return rcp_dynamic_cast(p1,false); } +#endif + +/** \brief Set extra data associated with a RCP object. + * + * @param extra_data + * [in] Data object that will be set (copied) + * @param name [in] The name given to the extra data. The value of + * name together with the data type T1 of the + * extra data must be unique from any other such data or + * the other data will be overwritten. + * @param p [out] On output, will be updated with the input extra_data + * @param destroy_when + * [in] Determines when extra_data will be destoryed + * in relation to the underlying reference-counted object. + * If destroy_when==PRE_DESTROY then extra_data + * will be deleted before the underlying reference-counted object. + * If destroy_when==POST_DESTROY (the default) then extra_data + * will be deleted after the underlying reference-counted object. + * @param force_unique + * [in] Determines if this type and name pair must be unique + * in which case if an object with this same type and name + * already exists, then an std::exception will be thrown. + * The default is true for safety. + * + * If there is a call to this function with the same type of extra + * data T1 and same arguments p and name + * has already been made, then the current piece of extra data already + * set will be overwritten with extra_data. However, if the + * type of the extra data T1 is different, then the extra + * data can be added and not overwrite existing extra data. This + * means that extra data is keyed on both the type and name. This + * helps to minimize the chance that clients will unexpectedly + * overwrite data by accident. + * + * When the last RefcountPtr object is removed and the + * reference-count node is deleted, then objects are deleted in the following + * order: (1) All of the extra data that where added with + * destroy_when==PRE_DESTROY are first, (2) then the underlying + * reference-counted object is deleted, and (3) the rest of the extra data + * that was added with destroy_when==PRE_DESTROY is then deleted. + * The order in which the objects are destroyed is not guaranteed. Therefore, + * clients should be careful not to add extra data that has deletion + * dependancies (instead consider using nested RCP objects as extra + * data which will guarantee the order of deletion). + * + * Preconditions:
      + *
    • p->get() != NULL (throws std::logic_error) + *
    • If this function has already been called with the same template + * type T1 for extra_data and the same std::string name + * and force_unique==true, then an std::invalid_argument + * std::exception will be thrown. + *
    + * + * Note, this function is made a non-member function to be consistent + * with the non-member get_extra_data() functions. + * + * \relates RCP + */ +template +void set_extra_data( + const T1 &extra_data, + const std::string& name, RCP *p, + EPrePostDestruction destroy_when = POST_DESTROY, + bool force_unique = true + ); + +/** \brief Get a non-const reference to extra data associated with a RCP object. + * + * @param p [in] Smart pointer object that extra data is being extraced from. + * @param name [in] Name of the extra data. + * + * @return Returns a non-const reference to the extra_data object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • name and T1 must have been used in a previous + * call to set_extra_data() (throws std::invalid_argument). + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * \relates RCP + */ +template +T1& get_extra_data( RCP& p, const std::string& name ); + +/** \brief Get a const reference to extra data associated with a RCP object. + * + * @param p [in] Smart pointer object that extra data is being extraced from. + * @param name [in] Name of the extra data. + * + * @return Returns a const reference to the extra_data object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • name and T1 must have been used in a previous + * call to set_extra_data() (throws std::invalid_argument). + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * Also note that this const version is a false sense of security + * since a client can always copy a const RCP object + * into a non-const object and then use the non-const version to + * change the data. However, its presence will help to avoid some + * types of accidental changes to this extra data. + * + * \relates RCP + */ +template +const T1& get_extra_data( const RCP& p, const std::string& name ); + +/** \brief Get a pointer to non-const extra data (if it exists) associated + * with a RCP object. + * + * @param p [in] Smart pointer object that extra data is being extraced from. + * @param name [in] Name of the extra data. + * + * @return Returns a non-const pointer to the extra_data object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If name and T1 have been used in a previous + * call to set_extra_data() then return !=NULL + * and otherwise return == NULL. + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * \relates RCP + */ +template +T1* get_optional_extra_data( RCP& p, const std::string& name ); + +/** \brief Get a pointer to const extra data (if it exists) associated with a RCP object. + * + * @param p [in] Smart pointer object that extra data is being extraced from. + * @param name [in] Name of the extra data. + * + * @return Returns a const pointer to the extra_data object if it exists. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If name and T1 have been used in a previous + * call to set_extra_data() then return !=NULL + * and otherwise return == NULL. + *
    + * + * Note, this function must be a non-member function since the client + * must manually select the first template argument. + * + * Also note that this const version is a false sense of security + * since a client can always copy a const RCP object + * into a non-const object and then use the non-const version to + * change the data. However, its presence will help to avoid some + * types of accidental changes to this extra data. + * + * \relates RCP + */ +template +const T1* get_optional_extra_data( const RCP& p, const std::string& name ); + +/** \brief Return a non-const reference to the underlying deallocator object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • The deallocator object type used to construct p is same as Dealloc_T + * (throws std::logic_error) + *
    + * + * \relates RCP + */ +template +Dealloc_T& get_dealloc( RCP& p ); + +/** \brief Return a const reference to the underlying deallocator object. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    • The deallocator object type used to construct p is same as Dealloc_T + * (throws std::logic_error) + *
    + * + * Note that the const version of this function provides only + * a very ineffective attempt to avoid accidental changes to the + * deallocation object. A client can always just create a new + * non-const RCP object from any + * const RCP object and then call the + * non-const version of this function. + * + * \relates RCP + */ +template +const Dealloc_T& get_dealloc( const RCP& p ); + +/** \brief Return a pointer to the underlying non-const deallocator + * object if it exists. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If the deallocator object type used to construct p is same as Dealloc_T + * then return!=NULL, otherwise return==NULL + *
    + * + * \relates RCP + */ +template +Dealloc_T* get_optional_dealloc( RCP& p ); + +/** \brief Return a pointer to the underlying const deallocator + * object if it exists. + * + * Preconditions:
      + *
    • p.get() != NULL (throws std::logic_error) + *
    + * + * Postconditions:
      + *
    • If the deallocator object type used to construct p is same as Dealloc_T + * then return!=NULL, otherwise return==NULL + *
    + * + * Note that the const version of this function provides only + * a very ineffective attempt to avoid accidental changes to the + * deallocation object. A client can always just create a new + * non-const RCP object from any + * const RCP object and then call the + * non-const version of this function. + * + * \relates RCP + */ +template +const Dealloc_T* get_optional_dealloc( const RCP& p ); + +/** \brief Output stream inserter. + * + * The implementation of this function just print pointer addresses and + * therefore puts not restrictions on the data types involved. + * + * \relates RCP + */ +template +std::ostream& operator<<( std::ostream& out, const RCP& p ); + +/** \brief Print the list of currently active RCP nodes. + * + * When the macro TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE is + * defined, this function will print out all of the RCP nodes that are + * currently active. This function can be called at any time during a + * program. + * + * When the macro TEUCHOS_SHOW_ACTIVE_REFCOUNTPTR_NODE_TRACE is + * defined this function will get called automatically after the program ends + * and all of the local and global RCP objects have been destroyed. If any + * RCP nodes are printed at that time, then this is an indication that there + * may be some circular references that will caused memory leaks. You memory + * checking tool such as valgrind or purify should complain about this! + * + * \relates RCP + */ +void print_active_RCP_nodes(std::ostream &out); + +} // end namespace Teuchos + +#endif // TEUCHOS_RCP_DECL_HPP diff --git a/fastlib/trilinos/include/Teuchos_Range1D.hpp b/fastlib/trilinos/include/Teuchos_Range1D.hpp new file mode 100644 index 0000000000..28f32eeb4a --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Range1D.hpp @@ -0,0 +1,313 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Range1D class used for representing a range of positive integers. +// Its primary usage is in accessing vectors and matrices by subregions +// of rows and columns +// + +#ifndef TEUCHOS_RANGE1D_HPP +#define TEUCHOS_RANGE1D_HPP + +/*! \file Teuchos_Range1D.hpp + \brief . +*/ + +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_TestForException.hpp" + +namespace Teuchos { + +/** \brief Subregion Index Range Class. + * + * The class %Range1D abstracts a 1-D, zero-based, range of indexes. + * It is used to index into vectors and matrices and return subregions of them + * respectively. + * + * Constructing using Range1D() yields a range that represents the + * entire dimension of an object [0, max_ubound-1] (an entire std::vector, + * all the rows in a matrix, or all the columns in a matrix etc.). + * + * Constructing using \ref Range1D::Range1D "Range1D(INVALID)" yields + * an invalid range [0,-1] with size() == 0. In fact the + * condition size()==0 is the determining flag that a range is not + * valid. Once constructed with Range1D(INVALID), a + * %Range1D object can pass through many other operations that may + * change %lbound() and %ubound() but will never change + * size()==0. + * + * Constructing using \ref Range1D::Range1D "Range1D(lbound,ubound)" + * yields a finite-dimensional zero-based range. The validity of constructed + * range will only be checked if TEUCHOS_DEBUG is defined. + * + * There are many \ref Range1D_funcs_grp "non-member functions" that can be + * used with %Range1D objects. + * + * The default copy constructor and assignment operator functions are allowed + * since they have the correct semantics. + */ +class Range1D { +public: + + /** \brief . */ + typedef Teuchos_Index Index; + + /** \brief . */ + enum EInvalidRange { INVALID }; + + /** \brief Used for Range1D(INVALID) */ + static const Range1D Invalid; + + /** \brief Constructs a range representing the entire range. + * + * Postconditions:
      + *
    • this->full_range()==true + *
    • this->size() is a very large number + *
    • this->lbound()==0 + *
    • this->ubound() is a very large number + *
    + */ + inline Range1D(); + + /** Constructs an invalid (zero) range. + * + * Postconditions:
      + *
    • this->full_range() == false + *
    • this->size() == 0 + *
    • this->lbound()==0 + *
    • this->ubound()==-1 + *
    + */ + inline Range1D( EInvalidRange ); + + /** \brief Constructs a range that represents the range [lbound, ubound]. + * + * Preconditions:
      + *
    • lbound >= 0 (throw \c range_error) + *
    • lbound <= ubound (throw \c range_error) + *
    + * + * Postconditions:
      + *
    • this->full_range() == false + *
    • this->size() == ubound - lbound + 1 + *
    • this->lbound() == lbound + *
    • this->ubound() == ubound + *
    + */ + inline Range1D(Index lbound, Index ubound); + + /** Returns \c true if the range represents the entire region (constructed + * from \c Range1D()) + */ + inline bool full_range() const; + + /** \brief Return lower bound of the range */ + inline Index lbound() const; + + /** \brief Return upper bound of the range */ + inline Index ubound() const; + + /** \brief Return the size of the range (ubound() - lbound() + 1) */ + inline Index size() const; + + /** \brief Return true if the index is in range */ + inline bool in_range(Index i) const; + + /** \brief Increment the range by a constant */ + inline Range1D& operator+=( Index incr ); + + /** \brief Deincrement the range by a constant */ + inline Range1D& operator-=( Index incr ); + +private: + Index lbound_; + Index ubound_; // = INT_MAX-1 flag for entire range + // lbound == ubound == 0 flag for invalid range. + + // assert that the range is valid + inline void assert_valid_range(Index lbound, Index ubound) const; + +}; // end class Range1D + +/** \brief rng1 == rng2. + * + * @return Returns rng1.lbound() == rng2.ubound() && rng1.ubound() == rng2.ubound(). + * + * \relates Range1D + */ +inline bool operator==(const Range1D& rng1, const Range1D& rng2 ) +{ + return rng1.lbound() == rng2.lbound() && rng1.ubound() == rng2.ubound(); +} + +/** \brief rng_lhs = rng_rhs + i. + * + * Increments the upper and lower bounds by a constant. + * + * Postcondition:
      + *
    • rng_lhs.lbound() == rng_rhs.lbound() + i + *
    • rng_lhs.ubound() == rng_rhs.ubound() + i + *
    + * + * \relates Range1D + */ +inline Range1D operator+(const Range1D &rng_rhs, Range1D::Index i) +{ + return Range1D(i+rng_rhs.lbound(), i+rng_rhs.ubound()); +} + +/** \brief rng_lhs = i + rng_rhs. + * + * Increments the upper and lower bounds by a constant. + * + * Postcondition:
      + *
    • rng_lhs.lbound() == i + rng_rhs.lbound() + *
    • rng_lhs.ubound() == i + rng_rhs.ubound() + *
    + * + * \relates Range1D + */ +inline Range1D operator+(Range1D::Index i, const Range1D &rng_rhs) +{ + return Range1D(i+rng_rhs.lbound(), i+rng_rhs.ubound()); +} + +/** \brief rng_lhs = rng_rhs - i. + * + * Deincrements the upper and lower bounds by a constant. + * + * Postcondition:
      + *
    • rng_lhs.lbound() == rng_rhs.lbound() - i + *
    • rng_lhs.ubound() == rng_rhs.ubound() - i + *
    + * + * \relates Range1D + */ +inline Range1D operator-(const Range1D &rng_rhs, Range1D::Index i) +{ + return Range1D(rng_rhs.lbound()-i, rng_rhs.ubound()-i); +} + +/** \brief Return a bounded index range from a potentially unbounded index + * range. + * + * Return a index range of lbound to ubound if rng.full_range() == true + * , otherwise just return a copy of rng. + * + * Postconditions:
      + *
    • [rng.full_range() == true] return.lbound() == lbound + *
    • [rng.full_range() == true] return.ubound() == ubound + *
    • [rng.full_range() == false] return.lbound() == rng.lbound() + *
    • [rng.full_range() == false] return.ubound() == rng.ubound() + *
    + * + * \relates Range1D + */ +inline Range1D full_range(const Range1D &rng, Range1D::Index lbound, Range1D::Index ubound) +{ return rng.full_range() ? Range1D(lbound,ubound) : rng; } + +// ////////////////////////////////////////////////////////// +// Inline members + +inline +Range1D::Range1D() + : lbound_(0), ubound_(INT_MAX-1) +{} + +inline +Range1D::Range1D( EInvalidRange ) + : lbound_(0), ubound_(-1) +{} + + +inline +Range1D::Range1D(Index lbound, Index ubound) + : lbound_(lbound), ubound_(ubound) +{ + assert_valid_range(lbound,ubound); +} + +inline +bool Range1D::full_range() const { + return ubound_ == INT_MAX-1; +} + +inline +Range1D::Index Range1D::lbound() const { + return lbound_; +} + +inline +Range1D::Index Range1D::ubound() const { + return ubound_; +} + +inline +Range1D::Index Range1D::size() const { + return ubound_ - lbound_ + 1; +} + +inline +bool Range1D::in_range(Index i) const { + return lbound_ <= i && i <= ubound_; +} + +inline +Range1D& Range1D::operator+=( Index incr ) { + assert_valid_range( lbound_ + incr, ubound_ + incr ); + lbound_ += incr; + ubound_ += incr; + return *this; +} + +inline +Range1D& Range1D::operator-=( Index incr ) { + assert_valid_range( lbound_ - incr, ubound_ - incr ); + lbound_ -= incr; + ubound_ -= incr; + return *this; +} + +// See Range1D.cpp +inline +void Range1D::assert_valid_range(int lbound, int ubound) const { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPTION( + lbound < 0, std::range_error + ,"Range1D::assert_valid_range(): Error, lbound ="< ubound, std::range_error + ,"Range1D::assert_valid_range(): Error, lbound = "< ubound = "<T
    is directly composed of + * datatypes that MPI can directly handle. This traits interface allows for + * specializations to create user-defined MPI_Datatype and + * MPI_Op objects to be returned from their static functions. + * + * \note + *
    • This class should not compile if it is instantiated by accident. + *
    • It should only be included if MPI is available and the MPI header + * must be included before this header file. + *
    • Template specializations exist for datatypes: char, int, + * float, and double. + *
    • A partial template specialization exists for std::complex + * where it is assumed that the real type T is directly handlable + * with MPI. + *
    • Only sum reductions are supported for all data types. + *
    • The reductions max and min are only supported by datatypes whee + * ScalarTraits::isComparable==true which is a compile-time + * boolean that can be used in template metaprogramming techniques. + *
    + */ +template class RawMPITraits { +public: + /** \brief Return the adjusted std::cout of items. */ + static int adjustCount(const int count) { bool *junk1; T *junk2 = &junk1; return 0; } // Should not compile! + /** \brief Return the raw MPI data type of the template argument. */ + static MPI_Datatype type() { bool *junk1; T *junk2 = &junk1; return MPI_DATATYPE_NULL; } // Should not compile! + /** \brief Return the MPI_Op object for a sum reduction */ + static MPI_Op sumOp() { bool *junk1; T *junk2 = &junk1; return MPI_OP_NULL; } // Should not compile! + /** \brief Return the MPI_Op object for a max reduction */ + static MPI_Op maxOp() { bool *junk1; T *junk2 = &junk1; return MPI_OP_NULL; } // Should not compile! + /** \brief Return the MPI_Op object for a min reduction */ + static MPI_Op minOp() { bool *junk1; T *junk2 = &junk1; return MPI_OP_NULL; } // Should not compile! +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +/** \brief Specialization of RawMPITraits for char + */ +template <> class RawMPITraits { +public: + /** \brief . */ + static int adjustCount(const int count) { return count; } + /** \brief . */ + static MPI_Datatype type() { return MPI_CHAR; } + /** \brief . */ + static MPI_Op sumOp() { return MPI_SUM; } + /** \brief . */ + static MPI_Op maxOp() { return MPI_MAX; } + /** \brief . */ + static MPI_Op minOp() { return MPI_MIN; } +}; + +/** \brief Specialization of RawMPITraits for int + */ +template <> class RawMPITraits { +public: + /** \brief . */ + static int adjustCount(const int count) { return count; } + /** \brief . */ + static MPI_Datatype type() { return MPI_INT; } + /** \brief . */ + static MPI_Op sumOp() { return MPI_SUM; } + /** \brief . */ + static MPI_Op maxOp() { return MPI_MAX; } + /** \brief . */ + static MPI_Op minOp() { return MPI_MIN; } +}; + +/** \brief Specialization of RawMPITraits for float + */ +template <> class RawMPITraits { +public: + /** \brief . */ + static int adjustCount(const int count) { return count; } + /** \brief . */ + static MPI_Datatype type() { return MPI_FLOAT; } + /** \brief . */ + static MPI_Op sumOp() { return MPI_SUM; } + /** \brief . */ + static MPI_Op maxOp() { return MPI_MAX; } + /** \brief . */ + static MPI_Op minOp() { return MPI_MIN; } +}; + +/** \brief Specialization of RawMPITraits for double + */ +template <> class RawMPITraits { +public: + /** \brief . */ + static int adjustCount(const int count) { return count; } + /** \brief . */ + static MPI_Datatype type() { return MPI_DOUBLE; } + /** \brief . */ + static MPI_Op sumOp() { return MPI_SUM; } + /** \brief . */ + static MPI_Op maxOp() { return MPI_MAX; } + /** \brief . */ + static MPI_Op minOp() { return MPI_MIN; } +}; + +/** \brief Partial specialization of RawMPITraits for std::complex. + * + * Note, maxOp() and minOp() are not supported by std::complex + * numbers. + * + * ToDo: If a platform is found where this simple implementation does not work + * then something else will have to be considered. + */ +template class RawMPITraits< std::complex > { +public: + /** \brief . */ + static int adjustCount(const int count) { return (2*count); } + /** \brief . */ + static MPI_Datatype type() { return RawMPITraits::type(); } + /** \brief . */ + static MPI_Op sumOp() { return MPI_SUM; } +}; + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} // namespace Teuchos + +#endif // TEUCHOS_RAW_MPI_TRAITS_H diff --git a/fastlib/trilinos/include/Teuchos_ReductionOp.hpp b/fastlib/trilinos/include/Teuchos_ReductionOp.hpp new file mode 100644 index 0000000000..45f49db2d7 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ReductionOp.hpp @@ -0,0 +1,70 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_REDUCTION_OP_HPP +#define TEUCHOS_REDUCTION_OP_HPP + +#include "Teuchos_Describable.hpp" + +namespace Teuchos { + +/** \brief Base interface class for user-defined reduction operations for + * objects that use value semantics. + * + * ToDo: Finish documentation! + */ +template +class ValueTypeReductionOp : public Describable { +public: + /** \brief . */ + virtual void reduce( + const Ordinal count + ,const T inBuffer[] + ,T inoutBuffer[] + ) const = 0; +}; + +/** \brief Base interface class for user-defined reduction operations for + * objects that use reference semantics. + * + * ToDo: Finish documentation! + */ +template +class ReferenceTypeReductionOp : public Describable { +public: + /** \brief . */ + virtual void reduce( + const Ordinal count + ,const T*const inBuffer[] + ,T*const inoutBuffer[] + ) const = 0; +}; + +} // namespace Teuchos + +#endif // TEUCHOS_REDUCTION_OP_HPP diff --git a/fastlib/trilinos/include/Teuchos_ReductionOpHelpers.hpp b/fastlib/trilinos/include/Teuchos_ReductionOpHelpers.hpp new file mode 100644 index 0000000000..fec9e5c483 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ReductionOpHelpers.hpp @@ -0,0 +1,156 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_REDUCTION_OP_HELPERS_HPP +#define TEUCHOS_REDUCTION_OP_HELPERS_HPP + +#include "Teuchos_ReductionOp.hpp" +#include "Teuchos_SerializationTraitsHelpers.hpp" +#include "Teuchos_SerializerHelpers.hpp" + +namespace Teuchos { + +/** \brief Decorator class that uses traits to convert to and from + * char[] to typed buffers for objects that use value semantics and + * then call a type-specific reduction object. + * + * ToDo: Finish Documentation! + */ +template +class CharToValueTypeReductionOp : public ValueTypeReductionOp +{ +public: + /** \brief . */ + CharToValueTypeReductionOp( + const RCP > &reductOp + ); + /** \brief . */ + void reduce( + const Ordinal charCount + ,const char charInBuffer[] + ,char charInoutBuffer[] + ) const; +private: + RCP > reductOp_; + // Not defined and not to be called! + CharToValueTypeReductionOp(); + CharToValueTypeReductionOp(const CharToValueTypeReductionOp&); + CharToValueTypeReductionOp& operator=(const CharToValueTypeReductionOp&); +}; + +/** \brief Decorator class that uses a strategy object to convert to and from + * char[] to typed buffers for objects that use reference semantics + * and then call a type-specific reduction object. + * + * ToDo: Finish Documentation! + */ +template +class CharToReferenceTypeReductionOp : public ValueTypeReductionOp +{ +public: + /** \brief . */ + CharToReferenceTypeReductionOp( + const RCP > &serializer + ,const RCP > &reductOp + ); + /** \brief . */ + void reduce( + const Ordinal charCount + ,const char charInBuffer[] + ,char charInoutBuffer[] + ) const; +private: + RCP > serializer_; + RCP > reductOp_; + // Not defined and not to be called! + CharToReferenceTypeReductionOp(); + CharToReferenceTypeReductionOp(const CharToReferenceTypeReductionOp&); + CharToReferenceTypeReductionOp& operator=(const CharToReferenceTypeReductionOp&); +}; + +// ///////////////////////////////////// +// Template implementations + +// +// CharToValueTypeReductionOp +// + +template +CharToValueTypeReductionOp::CharToValueTypeReductionOp( + const RCP > &reductOp + ) + :reductOp_(reductOp) +{} + +template +void CharToValueTypeReductionOp::reduce( + const Ordinal charCount + ,const char charInBuffer[] + ,char charInoutBuffer[] + ) const +{ + ConstValueTypeDeserializationBuffer + inBuffer(charCount,charInBuffer); + ValueTypeDeserializationBuffer + inoutBuffer(charCount,charInoutBuffer); + reductOp_->reduce( + inBuffer.getCount(),inBuffer.getBuffer(),inoutBuffer.getBuffer() + ); +} + +// +// CharToReferenceTypeReductionOp +// + +template +CharToReferenceTypeReductionOp::CharToReferenceTypeReductionOp( + const RCP > &serializer + ,const RCP > &reductOp + ) + :serializer_(serializer), reductOp_(reductOp) +{} + +template +void CharToReferenceTypeReductionOp::reduce( + const Ordinal charCount + ,const char charInBuffer[] + ,char charInoutBuffer[] + ) const +{ + ConstReferenceTypeDeserializationBuffer + inBuffer(*serializer_,charCount,charInBuffer); + ReferenceTypeDeserializationBuffer + inoutBuffer(*serializer_,charCount,charInoutBuffer); + reductOp_->reduce( + inBuffer.getCount(),inBuffer.getBuffer(),inoutBuffer.getBuffer() + ); +} + +} // namespace Teuchos + +#endif // TEUCHOS_REDUCTION_OP_HELPERS_HPP diff --git a/fastlib/trilinos/include/Teuchos_RefCountPtr.hpp b/fastlib/trilinos/include/Teuchos_RefCountPtr.hpp new file mode 100644 index 0000000000..87a6b039cd --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_RefCountPtr.hpp @@ -0,0 +1,35 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_REFCOUNTPTR_HPP +#define TEUCHOS_REFCOUNTPTR_HPP + +#include "Teuchos_RCP.hpp" +#include "Teuchos_RefCountPtrDecl.hpp" + +#endif // TEUCHOS_REFCOUNTPTR_HPP diff --git a/fastlib/trilinos/include/Teuchos_RefCountPtrDecl.hpp b/fastlib/trilinos/include/Teuchos_RefCountPtrDecl.hpp new file mode 100644 index 0000000000..924dc25ab6 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_RefCountPtrDecl.hpp @@ -0,0 +1,39 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_REFCOUNTPTR_DECL_HPP +#define TEUCHOS_REFCOUNTPTR_DECL_HPP + +#include "Teuchos_RCPDecl.hpp" + +/** \brief An evil define to handle backward compatability with code that + * has not be updated to use Teuchos::RCP yet. + */ +#define RefCountPtr RCP + +#endif // TEUCHOS_REFCOUNTPTR_DECL_HPP diff --git a/fastlib/trilinos/include/Teuchos_ScalarTraits.hpp b/fastlib/trilinos/include/Teuchos_ScalarTraits.hpp new file mode 100644 index 0000000000..cc1d417f0b --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_ScalarTraits.hpp @@ -0,0 +1,601 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 06.18.03 -- Minor formatting changes +// -- Changed calls to LAPACK objects to use new templates +// 07.08.03 -- Move into Teuchos package/namespace +// 07.11.03 -- Added ScalarTraits for ARPREC::mp_real +// 07.14.03 -- Fixed int rand() function (was set up to return a floating-point style random number) +// 07.17.03 -- Added squareroot() function + +#ifndef _TEUCHOS_SCALARTRAITS_HPP_ +#define _TEUCHOS_SCALARTRAITS_HPP_ + +/*! \file Teuchos_ScalarTraits.hpp + \brief Defines basic traits for the scalar field type. +*/ + +#include "Teuchos_ConfigDefs.hpp" + +#ifndef HAVE_NUMERIC_LIMITS +#include "Teuchos_LAPACK.hpp" +#endif + +#ifdef HAVE_TEUCHOS_ARPREC +#include "mp/mpreal.h" +#endif + +#ifdef HAVE_TEUCHOS_GNU_MP +#include "gmp.h" +#include "gmpxx.h" +#endif + +/*! \struct Teuchos::ScalarTraits + \brief This structure defines some basic traits for a scalar field type. + + Scalar traits are an essential part of templated codes. This structure offers + the basic traits of the templated scalar type, like defining zero and one, + and basic functions on the templated scalar type, like performing a square root. + + The functions in the templated base unspecialized struct are designed not to + compile (giving a nice compile-time error message) and therefore specializations + must be written for Scalar types actually used. + + \note +
      +
    1. The default defined specializations are provided for \c int, \c float, and \c double. +
    2. ScalarTraits can be used with the Arbitrary Precision Library ( \c http://crd.lbl.gov/~dhbailey/mpdist/ ) + by configuring Teuchos with \c --enable-teuchos-arprec and giving the appropriate paths to ARPREC. + Then ScalarTraits has the specialization: \c mp_real. +
    3. If Teuchos is configured with \c --enable-teuchos-std::complex then ScalarTraits also has + a parital specialization for all std::complex numbers of the form std::complex. +
    +*/ + +/* This is the default structure used by ScalarTraits to produce a compile time + error when the specialization does not exist for type T. +*/ +namespace Teuchos { + +template +struct UndefinedScalarTraits +{ + //! This function should not compile if there is an attempt to instantiate! + static inline T notDefined() { return T::this_type_is_missing_a_specialization(); } +}; + +template +struct ScalarTraits +{ + //! Madatory typedef for result of magnitude + typedef T magnitudeType; + //! Determines if scalar type is std::complex + static const bool isComplex = false; + //! Determines if scalar type supports relational operators such as <, >, <=, >=. + static const bool isComparable = false; + //! Determines if scalar type have machine-specific parameters (i.e. eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax() are supported) + static const bool hasMachineParameters = false; + //! Returns relative machine precision. + static inline magnitudeType eps() { return UndefinedScalarTraits::notDefined(); } + //! Returns safe minimum (sfmin), such that 1/sfmin does not overflow. + static inline magnitudeType sfmin() { return UndefinedScalarTraits::notDefined(); } + //! Returns the base of the machine. + static inline magnitudeType base() { return UndefinedScalarTraits::notDefined(); } + //! Returns \c eps*base. + static inline magnitudeType prec() { return UndefinedScalarTraits::notDefined(); } + //! Returns the number of (base) digits in the mantissa. + static inline magnitudeType t() { return UndefinedScalarTraits::notDefined(); } + //! Returns 1.0 when rounding occurs in addition, 0.0 otherwise + static inline magnitudeType rnd() { return UndefinedScalarTraits::notDefined(); } + //! Returns the minimum exponent before (gradual) underflow. + static inline magnitudeType emin() { return UndefinedScalarTraits::notDefined(); } + //! Returns the underflow threshold - \c base^(emin-1) + static inline magnitudeType rmin() { return UndefinedScalarTraits::notDefined(); } + //! Returns the largest exponent before overflow. + static inline magnitudeType emax() { return UndefinedScalarTraits::notDefined(); } + //! Overflow theshold - \c (base^emax)*(1-eps) + static inline magnitudeType rmax() { return UndefinedScalarTraits::notDefined(); } + //! Returns the magnitudeType of the scalar type \c a. + static inline magnitudeType magnitude(T a) { return UndefinedScalarTraits::notDefined(); } + //! Returns representation of zero for this scalar type. + static inline T zero() { return UndefinedScalarTraits::notDefined(); } + //! Returns representation of one for this scalar type. + static inline T one() { return UndefinedScalarTraits::notDefined(); } + //! Returns the real part of the scalar type \c a. + static inline magnitudeType real(T a) { return UndefinedScalarTraits::notDefined(); } + //! Returns the imaginary part of the scalar type \c a. + static inline magnitudeType imag(T a) { return UndefinedScalarTraits::notDefined(); } + //! Returns the conjugate of the scalar type \c a. + static inline T conjugate(T a) { return UndefinedScalarTraits::notDefined(); } + //! Returns a number that represents NaN. + static inline T nan() { return UndefinedScalarTraits::notDefined(); } + //! Returns true if x is NaN or Inf. + static inline bool isnaninf(const T& x) { return UndefinedScalarTraits::notDefined(); } + //! Seed the random number generator returned by random(). + static inline void seedrandom(unsigned int s) { int i; T t = &i; } + //! Returns a random number (between -one() and +one()) of this scalar type. + static inline T random() { return UndefinedScalarTraits::notDefined(); } + //! Returns the name of this scalar type. + static inline std::string name() { (void)UndefinedScalarTraits::notDefined(); return 0; } + //! Returns a number of magnitudeType that is the square root of this scalar type \c x. + static inline T squareroot(T x) { return UndefinedScalarTraits::notDefined(); } + //! Returns the result of raising one scalar \c x to the power \c y. + static inline T pow(T x, T y) { return UndefinedScalarTraits::notDefined(); } +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + + +void throwScalarTraitsNanInfError( const std::string &errMsg ); + + +#define TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( VALUE, MSG ) \ + if (isnaninf(VALUE)) { \ + std::ostringstream omsg; \ + omsg << MSG; \ + throwScalarTraitsNanInfError(omsg.str()); \ + } + + +template<> +struct ScalarTraits +{ + typedef char magnitudeType; + static const bool isComplex = false; + static const bool isComparable = true; + static const bool hasMachineParameters = false; + // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax() + static inline magnitudeType magnitude(char a) { return static_cast(std::fabs(static_cast(a))); } + static inline char zero() { return 0; } + static inline char one() { return 1; } + static inline char conjugate(char x) { return x; } + static inline char real(char x) { return x; } + static inline char imag(char x) { return 0; } + static inline void seedrandom(unsigned int s) { std::srand(s); } + //static inline char random() { return (-1 + 2*rand()); } // RAB: This version should be used to be consistent with others + static inline char random() { return std::rand(); } // RAB: This version should be used for an unsigned char, not char + static inline std::string name() { return "char"; } + static inline char squareroot(char x) { return (char) std::sqrt((double) x); } + static inline char pow(char x, char y) { return (char) std::pow((double)x,(double)y); } +}; + +template<> +struct ScalarTraits +{ + typedef int magnitudeType; + static const bool isComplex = false; + static const bool isComparable = true; + static const bool hasMachineParameters = false; + // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax() + static inline magnitudeType magnitude(int a) { return static_cast(std::fabs(static_cast(a))); } + static inline int zero() { return 0; } + static inline int one() { return 1; } + static inline int conjugate(int x) { return x; } + static inline int real(int x) { return x; } + static inline int imag(int x) { return 0; } + static inline void seedrandom(unsigned int s) { std::srand(s); } + //static inline int random() { return (-1 + 2*rand()); } // RAB: This version should be used to be consistent with others + static inline int random() { return std::rand(); } // RAB: This version should be used for an unsigned int, not int + static inline std::string name() { return "int"; } + static inline int squareroot(int x) { return (int) std::sqrt((double) x); } + static inline int pow(int x, int y) { return (int) std::pow((double)x,(double)y); } +}; + +#ifndef __sun +extern const float flt_nan; +#endif + +template<> +struct ScalarTraits +{ + typedef float magnitudeType; + static const bool isComplex = false; + static const bool isComparable = true; + static const bool hasMachineParameters = true; + static inline float eps() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::epsilon(); +#else + LAPACK lp; return lp.LAMCH('E'); +#endif + } + static inline float sfmin() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::min(); +#else + LAPACK lp; return lp.LAMCH('S'); +#endif + } + static inline float base() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::radix; +#else + LAPACK lp; return lp.LAMCH('B'); +#endif + } + static inline float prec() { +#ifdef HAVE_NUMERIC_LIMITS + return eps()*base(); +#else + LAPACK lp; return lp.LAMCH('P'); +#endif + } + static inline float t() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::digits; +#else + LAPACK lp; return lp.LAMCH('N'); +#endif + } + static inline float rnd() { +#ifdef HAVE_NUMERIC_LIMITS + return ( std::numeric_limits::round_style == std::round_to_nearest ? float(1.0) : float(0.0) ); +#else + LAPACK lp; return lp.LAMCH('R'); +#endif + } + static inline float emin() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::min_exponent; +#else + LAPACK lp; return lp.LAMCH('M'); +#endif + } + static inline float rmin() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::min(); +#else + LAPACK lp; return lp.LAMCH('U'); +#endif + } + static inline float emax() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::max_exponent; +#else + LAPACK lp; return lp.LAMCH('L'); +#endif + } + static inline float rmax() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::max(); +#else + LAPACK lp; return lp.LAMCH('O'); +#endif + } + static inline magnitudeType magnitude(float a) + { +#ifdef TEUCHOS_DEBUG + TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( + a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" ); +#endif + return std::fabs(a); + } + static inline float zero() { return(0.0); } + static inline float one() { return(1.0); } + static inline float conjugate(float x) { return(x); } + static inline float real(float x) { return x; } + static inline float imag(float x) { return 0; } + static inline float nan() { +#ifdef __sun + return 0.0/std::sin(0.0); +#else + return flt_nan; +#endif + } + static inline bool isnaninf(float x) { // RAB: 2004/05/28: Taken from NOX_StatusTest_FiniteValue.C + const float tol = 1e-6; // Any (bounded) number should do! + if( !(x <= tol) && !(x > tol) ) return true; // IEEE says this should fail for NaN + float z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true; // Use fact that Inf*0 = NaN + return false; + } + static inline void seedrandom(unsigned int s) { std::srand(s); } + static inline float random() { float rnd = (float) std::rand() / RAND_MAX; return (float)(-1.0 + 2.0 * rnd); } + static inline std::string name() { return "float"; } + static inline float squareroot(float x) + { +#ifdef TEUCHOS_DEBUG + TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( + x, "Error, the input value to squareroot(...) x = " << x << " can not be NaN!" ); +#endif + errno = 0; + const float rtn = std::sqrt(x); + if (errno) + return nan(); + return rtn; + } + static inline float pow(float x, float y) { return std::pow(x,y); } +}; + +#ifndef __sun +extern const double dbl_nan; +#endif + +template<> +struct ScalarTraits +{ + typedef double magnitudeType; + static const bool isComplex = false; + static const bool isComparable = true; + static const bool hasMachineParameters = true; + static inline double eps() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::epsilon(); +#else + LAPACK lp; return lp.LAMCH('E'); +#endif + } + static inline double sfmin() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::min(); +#else + LAPACK lp; return lp.LAMCH('S'); +#endif + } + static inline double base() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::radix; +#else + LAPACK lp; return lp.LAMCH('B'); +#endif + } + static inline double prec() { +#ifdef HAVE_NUMERIC_LIMITS + return eps()*base(); +#else + LAPACK lp; return lp.LAMCH('P'); +#endif + } + static inline double t() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::digits; +#else + LAPACK lp; return lp.LAMCH('N'); +#endif + } + static inline double rnd() { +#ifdef HAVE_NUMERIC_LIMITS + return ( std::numeric_limits::round_style == std::round_to_nearest ? double(1.0) : double(0.0) ); +#else + LAPACK lp; return lp.LAMCH('R'); +#endif + } + static inline double emin() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::min_exponent; +#else + LAPACK lp; return lp.LAMCH('M'); +#endif + } + static inline double rmin() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::min(); +#else + LAPACK lp; return lp.LAMCH('U'); +#endif + } + static inline double emax() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::max_exponent; +#else + LAPACK lp; return lp.LAMCH('L'); +#endif + } + static inline double rmax() { +#ifdef HAVE_NUMERIC_LIMITS + return std::numeric_limits::max(); +#else + LAPACK lp; return lp.LAMCH('O'); +#endif + } + static inline magnitudeType magnitude(double a) + { +#ifdef TEUCHOS_DEBUG + TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( + a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" ); +#endif + return std::fabs(a); + } + static inline double zero() { return 0.0; } + static inline double one() { return 1.0; } + static inline double conjugate(double x) { return(x); } + static inline double real(double x) { return(x); } + static inline double imag(double x) { return(0); } + static inline double nan() { +#ifdef __sun + return 0.0/std::sin(0.0); +#else + return dbl_nan; +#endif + } + static inline bool isnaninf(double x) { // RAB: 2004/05/28: Taken from NOX_StatusTest_FiniteValue.C + const double tol = 1e-6; // Any (bounded) number should do! + if( !(x <= tol) && !(x > tol) ) return true; // IEEE says this should fail for NaN + double z=0.0*x; if( !(z <= tol) && !(z > tol) ) return true; // Use fact that Inf*0 = NaN + return false; + } + static inline void seedrandom(unsigned int s) { std::srand(s); } + static inline double random() { double rnd = (double) std::rand() / RAND_MAX; return (double)(-1.0 + 2.0 * rnd); } + static inline std::string name() { return "double"; } + static inline double squareroot(double x) + { +#ifdef TEUCHOS_DEBUG + TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( + x, "Error, the input value to squareroot(...) x = " << x << " can not be NaN!" ); +#endif + errno = 0; + const double rtn = std::sqrt(x); + if (errno) + return nan(); + return rtn; + } + static inline double pow(double x, double y) { return std::pow(x,y); } +}; + +#ifdef HAVE_TEUCHOS_GNU_MP + +extern gmp_randclass gmp_rng; + +template<> +struct ScalarTraits +{ + typedef mpf_class magnitudeType; + static const bool isComplex = false; + static const bool isComparable = true; + static const bool hasMachineParameters = false; + // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax() + static magnitudeType magnitude(mpf_class a) { return std::abs(a); } + static inline mpf_class zero() { mpf_class zero = 0.0; return zero; } + static inline mpf_class one() { mpf_class one = 1.0; return one; } + static inline mpf_class conjugate(mpf_class x) { return x; } + static inline mpf_class real(mpf_class x) { return(x); } + static inline mpf_class imag(mpf_class x) { return(0); } + static inline bool isnaninf(mpf_class x) { return false; } // mpf_class currently can't handle nan or inf! + static inline void seedrandom(unsigned int s) { + unsigned long int seedVal = static_cast(s); + gmp_rng.seed( seedVal ); + } + static inline mpf_class random() { + return gmp_rng.get_f(); + } + static inline std::string name() { return "mpf_class"; } + static inline mpf_class squareroot(mpf_class x) { return std::sqrt(x); } + static inline mpf_class pow(mpf_class x, mpf_class y) { return pow(x,y); } + // Todo: RAB: 2004/05/28: Add nan() and isnaninf() functions when needed! +}; + +#endif + +#ifdef HAVE_TEUCHOS_ARPREC + +template<> +struct ScalarTraits +{ + typedef mp_real magnitudeType; + static const bool isComplex = false; + static const bool isComparable = true; + static const bool hasMachineParameters = false; + // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax() + static magnitudeType magnitude(mp_real a) { return std::abs(a); } + static inline mp_real zero() { mp_real zero = 0.0; return zero; } + static inline mp_real one() { mp_real one = 1.0; return one; } + static inline mp_real conjugate(mp_real x) { return x; } + static inline mp_real real(mp_real x) { return(x); } + static inline mp_real imag(mp_real x) { return(0); } + static inline bool isnaninf(mp_real x) { return false; } // ToDo: Change this? + static inline void seedrandom(unsigned int s) { + long int seedVal = static_cast(s); + srand48(seedVal); + } + static inline mp_real random() { return mp_rand(); } + static inline std::string name() { return "mp_real"; } + static inline mp_real squareroot(mp_real x) { return std::sqrt(x); } + static inline mp_real pow(mp_real x, mp_real y) { return pow(x,y); } + // Todo: RAB: 2004/05/28: Add nan() and isnaninf() functions when needed! +}; + +#endif // HAVE_TEUCHOS_ARPREC + +#if ( defined(HAVE_COMPLEX) || defined(HAVE_COMPLEX_H) ) && defined(HAVE_TEUCHOS_COMPLEX) + +// Partial specialization for std::complex numbers templated on real type T +template +struct ScalarTraits< +#if defined(HAVE_COMPLEX) + std::complex +#elif defined(HAVE_COMPLEX_H) +std::complex +#endif +> +{ +#if defined(HAVE_COMPLEX) + typedef std::complex ComplexT; +#elif defined(HAVE_COMPLEX_H) + typedef std::complex ComplexT; +#endif + typedef typename ScalarTraits::magnitudeType magnitudeType; + static const bool isComplex = true; + static const bool isComparable = false; + static const bool hasMachineParameters = true; + static inline magnitudeType eps() { return ScalarTraits::eps(); } + static inline magnitudeType sfmin() { return ScalarTraits::sfmin(); } + static inline magnitudeType base() { return ScalarTraits::base(); } + static inline magnitudeType prec() { return ScalarTraits::prec(); } + static inline magnitudeType t() { return ScalarTraits::t(); } + static inline magnitudeType rnd() { return ScalarTraits::rnd(); } + static inline magnitudeType emin() { return ScalarTraits::emin(); } + static inline magnitudeType rmin() { return ScalarTraits::rmin(); } + static inline magnitudeType emax() { return ScalarTraits::emax(); } + static inline magnitudeType rmax() { return ScalarTraits::rmax(); } + static magnitudeType magnitude(ComplexT a) + { +#ifdef TEUCHOS_DEBUG + TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( + a, "Error, the input value to magnitude(...) a = " << a << " can not be NaN!" ); +#endif + return std::abs(a); + } + static inline ComplexT zero() { return ComplexT(ScalarTraits::zero(),ScalarTraits::zero()); } + static inline ComplexT one() { return ComplexT(ScalarTraits::one(),ScalarTraits::zero()); } + static inline ComplexT conjugate(ComplexT a){ return ComplexT(a.real(),-a.imag()); } + static inline magnitudeType real(ComplexT a) { return a.real(); } + static inline magnitudeType imag(ComplexT a) { return a.imag(); } + static inline ComplexT nan() { return ComplexT(ScalarTraits::nan(),ScalarTraits::nan()); } + static inline bool isnaninf(ComplexT x) { return ScalarTraits::isnaninf(x.real()) || ScalarTraits::isnaninf(x.imag()); } + static inline void seedrandom(unsigned int s) { ScalarTraits::seedrandom(s); } + static inline ComplexT random() + { + const T rnd1 = ScalarTraits::random(); + const T rnd2 = ScalarTraits::random(); + return ComplexT(rnd1,rnd2); + } + static inline std::string name() { return std::string("std::complex<")+std::string(ScalarTraits::name())+std::string(">"); } + // This will only return one of the square roots of x, the other can be obtained by taking its conjugate + static inline ComplexT squareroot(ComplexT x) + { +#ifdef TEUCHOS_DEBUG + TEUCHOS_SCALAR_TRAITS_NAN_INF_ERR( + x, "Error, the input value to squareroot(...) x = " << x << " can not be NaN!" ); +#endif + typedef ScalarTraits STMT; + const T r = x.real(), i = x.imag(); + const T a = STMT::squareroot((r*r)+(i*i)); + const T nr = STMT::squareroot((a+r)/2); + const T ni = STMT::squareroot((a-r)/2); + return ComplexT(nr,ni); + } + static inline ComplexT pow(ComplexT x, ComplexT y) { return pow(x,y); } +}; + +#endif // HAVE_COMPLEX || HAVE_COMPLEX_H + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} // Teuchos namespace + +#endif // _TEUCHOS_SCALARTRAITS_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_SerialDenseMatrix.hpp b/fastlib/trilinos/include/Teuchos_SerialDenseMatrix.hpp new file mode 100644 index 0000000000..f1c29e2b83 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_SerialDenseMatrix.hpp @@ -0,0 +1,895 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 06.18.03 -- Removed comments/documentation; file too hard to edit otherwise. Will replace later. +// -- Begin conversion from template to +// 06.23.03 -- Finished conversion from to +// -- Tpetra_DenseMatrix.cpp is now obsolete +// -- Added new constructor to allow construction of a submatrix +// -- Altered copyMat to enable its use in new constructor +// -- Commented out broken print() function +// -- Fixed oneNorm() (uninitialized return variable was causing erroneous results) +// 06.24.03 -- Minor formatting changes +// 07.01.03 -- Added TempPrint() function to temporarily take the place of print() and operator<< while I figure out how to fix them +// 07.02.03 -- Added operator== and operator!= to make testing programs easier to write/read. Implementation of == isn't the most +// efficient/robust, but it works. Will consider optimizing later. +// -- Warning! Constructor DenseMatrix(DataAccess, const DenseMatrix &, int, int, int, int) (the +// "submatrix grabber" constructor) does not work correctly when used with CV == View (always grabs submatrix from top +// left corner). +// 07.07.03 -- Constructor bug detailed above (07.02) is now corrected (hopefully). +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef _TEUCHOS_SERIALDENSEMATRIX_HPP_ +#define _TEUCHOS_SERIALDENSEMATRIX_HPP_ +/*! \file Teuchos_SerialDenseMatrix.hpp + \brief Templated serial dense matrix class +*/ + +#include "Teuchos_CompObject.hpp" +#include "Teuchos_BLAS.hpp" +#include "Teuchos_ScalarTraits.hpp" +#include "Teuchos_DataAccess.hpp" +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_TestForException.hpp" + +/*! \class Teuchos::SerialDenseMatrix + \brief This class creates and provides basic support for dense rectangular matrix of templated type. +*/ +/** \example DenseMatrix/cxx_main.cpp + This is an example of how to use the Teuchos::SerialDenseMatrix class. +*/ + + +namespace Teuchos { + + template + class SerialDenseMatrix : public CompObject, public Object, public BLAS + { + public: + + //! @name Constructor/Destructor methods. + //@{ + + //! Default Constructor + /*! Creates a empty matrix of no dimension. The Shaping methods should be used to size this matrix. + Values of this matrix should be set using the [], (), or = operators. + */ + SerialDenseMatrix(); + + //! Shaped Constructor + /*! + \param numRows - Number of rows in matrix. + \param numCols - Number of columns in matrix. + + Creates a shaped matrix with \c numRows rows and \c numCols cols. All values are initialized to 0. + Values of this matrix should be set using the [] or the () operators. + */ + SerialDenseMatrix(OrdinalType numRows, OrdinalType numCols); + + //! Shaped Constructor with Values + /*! + \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View. + \param values - Pointer to an array of ScalarType. The first column starts at \c values, + the second at \c values+stride, etc. + \param stride - The stride between the columns of the matrix in memory. + \param numRows - Number of rows in matrix. + \param numCols - Number of columns in matrix. + */ + SerialDenseMatrix(DataAccess CV, ScalarType* values, OrdinalType stride, OrdinalType numRows, OrdinalType numCols); + + //! Copy Constructor + /*! \note A deep copy of the \c Source transposed can be obtained if \c trans=Teuchos::TRANS, \c else + a non-transposed copy of \c Source is made. There is no storage of the transpose state of the matrix + within the SerialDenseMatrix class, so this information will not propogate to any operation performed + on a matrix that has been copy constructed in transpose. + */ + SerialDenseMatrix(const SerialDenseMatrix &Source, ETransp trans = Teuchos::NO_TRANS); + + //! Submatrix Copy Constructor + /*! + \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View. + \param Source - Reference to another dense matrix from which values are to be copied. + \param numRows - The number of rows in this matrix. + \param numCols - The number of columns in this matrix. + \param startRow - The row of \c Source from which the submatrix copy should start. + \param startCol - The column of \c Source from which the submatrix copy should start. + + Creates a shaped matrix with \c numRows rows and \c numCols columns, which is a submatrix of \c Source. + If \c startRow and \c startCol are not given, then the submatrix is the leading submatrix of \c Source. + Otherwise, the (1,1) entry in the copied matrix is the (\c startRow, \c startCol) entry of \c Source. + */ + SerialDenseMatrix(DataAccess CV, const SerialDenseMatrix &Source, OrdinalType numRows, OrdinalType numCols, OrdinalType startRow=0, OrdinalType startCol=0); + + //! Destructor + virtual ~SerialDenseMatrix(); + //@} + + //! @name Shaping methods. + //@{ + //! Shape method for changing the size of a SerialDenseMatrix, initializing entries to zero. + /*! + \param numRows - The number of rows in this matrix. + \param numCols - The number of columns in this matrix. + + This method allows the user to define the dimensions of a SerialDenseMatrix at any point. This method + can be called at any point after construction. Any values previously in this object will be destroyed + and the resized matrix starts of with all zero values. + + \return Integer error code, set to 0 if successful. + */ + int shape(OrdinalType numRows, OrdinalType numCols); + + //! Same as shape() except leaves uninitialized. + int shapeUninitialized(OrdinalType numRows, OrdinalType numCols); + + //! Reshaping method for changing the size of a SerialDenseMatrix, keeping the entries. + /*! + \param numRows - The number of rows in this matrix. + \param numCols - The number of columns in this matrix. + + This method allows the user to redefine the dimensions of a SerialDenseMatrix at any point. This method + can be called at any point after construction. Any values previously in this object will be copied into + the reshaped matrix. + + \return Integer error code, set 0 if successful. + */ + int reshape(OrdinalType numRows, OrdinalType numCols); + + + //@} + + //! @name Set methods. + //@{ + + //! Copies values from one matrix to another. + /*! + The operator= copies the values from one existing SerialDenseMatrix to another. + If \c Source is a view (i.e. CV = Teuchos::View), then this method will + return a view. Otherwise, it will return a copy of \c Source. \e this object + will be resized if it is not large enough to copy \c Source into. + */ + SerialDenseMatrix& operator= (const SerialDenseMatrix& Source); + + //! Copies values from one matrix to another. + /*! + The operator= copies the values from one existing SerialDenseMatrix to another + if the dimension of both matrices are the same. If not, \e this matrix + will be returned unchanged. + */ + SerialDenseMatrix& assign (const SerialDenseMatrix& Source); + + //! Set all values in the matrix to a constant value. + /*! + \param value - Value to use; zero if none specified. + \return Integer error code, set to 0 if successful. + */ + int putScalar( const ScalarType value = Teuchos::ScalarTraits::zero() ); + + //! Set all values in the matrix to be random numbers. + int random(); + + //@} + + //! @name Accessor methods. + //@{ + + //! Element access method (non-const). + /*! Returns the element in the ith row and jth column if A(i,j) is specified, the + expression A[j][i] will return the same element. + + \return Element from the specified \c rowIndex row and \c colIndex column. + \warning The validity of \c rowIndex and \c colIndex will only be checked if Teuchos is + configured with --enable-teuchos-abc. + */ + ScalarType& operator () (OrdinalType rowIndex, OrdinalType colIndex); + + //! Element access method (const). + /*! Returns the element in the ith row and jth column if A(i,j) is specified, the expression + A[j][i] will return the same element. + + \return Element from the specified \c rowIndex row and \c colIndex column. + \warning The validity of \c rowIndex and \c colIndex will only be checked if Teuchos is + configured with --enable-teuchos-abc. + */ + const ScalarType& operator () (OrdinalType rowIndex, OrdinalType colIndex) const; + + //! Column access method (non-const). + /*! Returns the pointer to the ScalarType array at the jth column if A[j] is specified, the expression + A[j][i] will return the same element as A(i,j). + + \return Pointer to the ScalarType array at the \c colIndex column ( \c values_+colIndex*stride_ ). + \warning The validity of \c colIndex will only be checked if Teuchos is configured with + --enable-teuchos-abc. + */ + ScalarType* operator [] (OrdinalType colIndex); + + //! Column access method (const). + /*! Returns the pointer to the ScalarType array at the jth column if A[j] is specified, the expression + A[j][i] will return the same element as A(i,j). + + \return Pointer to the ScalarType array at the \c colIndex column ( \c values_+colIndex*stride_ ). + \warning The validity of \c colIndex will only be checked if Teuchos is configured with + --enable-teuchos-abc. + */ + const ScalarType* operator [] (OrdinalType colIndex) const; + + //! Data array access method. + /*! \return Pointer to the ScalarType data array contained in the object. */ + ScalarType* values() const { return(values_); } + + //@} + + //! @name Mathematical methods. + //@{ + + //! Add another matrix to \e this matrix. + /*! Add \c Source to \e this if the dimension of both matrices are the same. If not, \e this matrix + will be returned unchanged. + */ + SerialDenseMatrix& operator+= (const SerialDenseMatrix& Source); + + //! Subtract another matrix from \e this matrix. + /*! Subtract \c Source from \e this if the dimension of both matrices are the same. If not, \e this matrix + will be returned unchanged. + */ + SerialDenseMatrix& operator-= (const SerialDenseMatrix& Source); + + //! Scale \c this matrix by \c alpha; \c *this = \c alpha*\c *this. + /*! + \param alpha Scalar to multiply \e this by. + \return Integer error code, set to 0 if successful. + */ + int scale ( const ScalarType alpha ); + + //! Point-wise scale \c this matrix by \c A; i.e. *this(i,j) *= A(i,j) + /*! The values of \c *this matrix will be point-wise scaled by the values in A. + If A and \c this matrix are not the same dimension \c this will be returned unchanged. + + \param B Teuchos::SerialDenseMatrix used to perform element-wise scaling of \e this. + \return Integer error code, set to 0 if successful. + */ + int scale ( const SerialDenseMatrix& A ); + + //! Multiply \c A * \c B and add them to \e this; \e this = \c beta * \e this + \c alpha*A*B. + /*! + \param transa - Use the transpose of \c A if transa = Teuchos::TRANS, else don't use the + transpose if transa = Teuchos::NOTRANS. + \param transb - Use the transpose of \c B if transb = Teuchos::TRANS, else don't use the + transpose if transb = Teuchos::NOTRANS. + \param alpha - The scaling factor for \c A * \c B. + \param A - SerialDenseMatrix + \param B - SerialDenseMatrix + \param beta - The scaling factor for \e this. + + If the matrices \c A and \c B are not of the right dimension, consistent with \e this, then \e this + matrix will not be altered and -1 will be returned. + \return Integer error code, set to 0 if successful. + */ + int multiply (ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix &A, const SerialDenseMatrix &B, ScalarType beta); + //@} + + //! @name Comparison methods. + //@{ + + //! Equality of two matrices. + /*! \return True if \e this matrix and \c Operand are of the same shape (rows and columns) and have + the same entries, else False will be returned. + */ + bool operator== (const SerialDenseMatrix &Operand); + + //! Inequality of two matrices. + /*! \return True if \e this matrix and \c Operand of not of the same shape (rows and columns) or don't + have the same entries, else False will be returned. + */ + bool operator!= (const SerialDenseMatrix &Operand); + + //@} + + //! @name Attribute methods. + //@{ + + //! Returns the row dimension of this matrix. + OrdinalType numRows() const { return(numRows_); } + + //! Returns the column dimension of this matrix. + OrdinalType numCols() const { return(numCols_); } + + //! Returns the stride between the columns of this matrix in memory. + OrdinalType stride() const { return(stride_); } + //@} + + //! @name Norm methods. + //@{ + + //! Returns the 1-norm of the matrix. + typename ScalarTraits::magnitudeType normOne() const; + + //! Returns the Infinity-norm of the matrix. + typename ScalarTraits::magnitudeType normInf() const; + + //! Returns the Frobenius-norm of the matrix. + typename ScalarTraits::magnitudeType normFrobenius() const; + //@} + + //! @name I/O methods. + //@{ + //! Print method. Defines the behavior of the std::ostream << operator inherited from the Object class. + virtual void print(std::ostream& os) const; + + //@} + protected: + void copyMat(ScalarType* inputMatrix, OrdinalType strideInput, OrdinalType numRows, OrdinalType numCols, ScalarType* outputMatrix, OrdinalType strideOutput, OrdinalType startRow, OrdinalType startCol, ScalarType alpha = ScalarTraits::zero() ); + void deleteArrays(); + void checkIndex( OrdinalType rowIndex, OrdinalType colIndex = 0 ) const; + OrdinalType numRows_; + OrdinalType numCols_; + OrdinalType stride_; + bool valuesCopied_; + ScalarType* values_; + + }; // class Teuchos_SerialDenseMatrix + + //---------------------------------------------------------------------------------------------------- + // Constructors and Destructor + //---------------------------------------------------------------------------------------------------- + + template + SerialDenseMatrix::SerialDenseMatrix() : CompObject(), numRows_(0), numCols_(0), stride_(0), valuesCopied_(false), values_(0) {} + + template + SerialDenseMatrix::SerialDenseMatrix( OrdinalType numRows, OrdinalType numCols ) : CompObject(), numRows_(numRows), numCols_(numCols), stride_(numRows) + { + values_ = new ScalarType[stride_*numCols_]; + putScalar(); + valuesCopied_ = true; + } + + template + SerialDenseMatrix::SerialDenseMatrix(DataAccess CV, ScalarType* values, OrdinalType stride, OrdinalType numRows, OrdinalType numCols) : CompObject(), numRows_(numRows), numCols_(numCols), stride_(stride), valuesCopied_(false), values_(values) + { + if(CV == Copy) + { + stride_ = numRows_; + values_ = new ScalarType[stride_*numCols_]; + copyMat(values, stride, numRows_, numCols_, values_, stride_, 0, 0, false); + valuesCopied_ = true; + } + } + + template + SerialDenseMatrix::SerialDenseMatrix(const SerialDenseMatrix &Source, ETransp trans) : CompObject(), numRows_(0), numCols_(0), stride_(0), valuesCopied_(true), values_(0) + { + if ( trans == Teuchos::NO_TRANS ) + { + numRows_ = Source.numRows_; + numCols_ = Source.numCols_; + stride_ = numRows_; + values_ = new ScalarType[stride_*numCols_]; + copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0, false); + } + else if ( trans == Teuchos::CONJ_TRANS && ScalarTraits::isComplex ) + { + numRows_ = Source.numCols_; + numCols_ = Source.numRows_; + stride_ = numRows_; + values_ = new ScalarType[stride_*numCols_]; + for (OrdinalType j=0; j::conjugate(Source.values_[i*Source.stride_ + j]); + } + } + } + else + { + numRows_ = Source.numCols_; + numCols_ = Source.numRows_; + stride_ = numRows_; + values_ = new ScalarType[stride_*numCols_]; + for (OrdinalType j=0; j + SerialDenseMatrix::SerialDenseMatrix(DataAccess CV, const SerialDenseMatrix &Source, OrdinalType numRows, OrdinalType numCols, OrdinalType startRow, OrdinalType startCol) : CompObject(), numRows_(numRows), numCols_(numCols), stride_(Source.stride_), valuesCopied_(false), values_(Source.values_) + { + if(CV == Copy) + { + stride_ = numRows; + values_ = new ScalarType[stride_ * numCols]; + copyMat(Source.values_, Source.stride_, numRows, numCols, values_, stride_, startRow, startCol, false); + valuesCopied_ = true; + } + else // CV == View + { + values_ = values_ + (stride_ * startCol) + startRow; + } + } + + template + SerialDenseMatrix::~SerialDenseMatrix() + { + deleteArrays(); + } + + //---------------------------------------------------------------------------------------------------- + // Shape methods + //---------------------------------------------------------------------------------------------------- + + template + int SerialDenseMatrix::shape(OrdinalType numRows, OrdinalType numCols) + { + deleteArrays(); // Get rid of anything that might be already allocated + numRows_ = numRows; + numCols_ = numCols; + stride_ = numRows_; + values_ = new ScalarType[stride_*numCols_]; + putScalar(); + valuesCopied_ = true; + return(0); + } + + template + int SerialDenseMatrix::shapeUninitialized(OrdinalType numRows, OrdinalType numCols) + { + deleteArrays(); // Get rid of anything that might be already allocated + numRows_ = numRows; + numCols_ = numCols; + stride_ = numRows_; + values_ = new ScalarType[stride_*numCols_]; + valuesCopied_ = true; + return(0); + } + + template + int SerialDenseMatrix::reshape(OrdinalType numRows, OrdinalType numCols) + { + // Allocate space for new matrix + ScalarType* values_tmp = new ScalarType[numRows * numCols]; + ScalarType zero = ScalarTraits::zero(); + for(OrdinalType k = 0; k < numRows * numCols; k++) + { + values_tmp[k] = zero; + } + OrdinalType numRows_tmp = TEUCHOS_MIN(numRows_, numRows); + OrdinalType numCols_tmp = TEUCHOS_MIN(numCols_, numCols); + if(values_ != 0) + { + copyMat(values_, stride_, numRows_tmp, numCols_tmp, values_tmp, numRows, 0, 0, false); // Copy principal submatrix of A to new A + } + deleteArrays(); // Get rid of anything that might be already allocated + numRows_ = numRows; + numCols_ = numCols; + stride_ = numRows_; + values_ = values_tmp; // Set pointer to new A + valuesCopied_ = true; + return(0); + } + + //---------------------------------------------------------------------------------------------------- + // Set methods + //---------------------------------------------------------------------------------------------------- + + template + int SerialDenseMatrix::putScalar( const ScalarType value ) + { + // Set each value of the dense matrix to "value". + for(OrdinalType j = 0; j < numCols_; j++) + { + for(OrdinalType i = 0; i < numRows_; i++) + { + values_[i + j*stride_] = value; + } + } + return 0; + } + + template + int SerialDenseMatrix::random() + { + // Set each value of the dense matrix to a random value. + for(OrdinalType j = 0; j < numCols_; j++) + { + for(OrdinalType i = 0; i < numRows_; i++) + { + values_[i + j*stride_] = ScalarTraits::random(); + } + } + return 0; + } + + template + SerialDenseMatrix& SerialDenseMatrix::operator= (const SerialDenseMatrix& Source) { + if(this == &Source) + return(*this); // Special case of source same as target + if((!valuesCopied_) && (!Source.valuesCopied_) && (values_ == Source.values_)) + return(*this); // Special case of both are views to same data. + + // If the source is a view then we will return a view, else we will return a copy. + if (!Source.valuesCopied_) { + if(valuesCopied_) { + // Clean up stored data if this was previously a copy. + deleteArrays(); + } + numRows_ = Source.numRows_; + numCols_ = Source.numCols_; + stride_ = Source.stride_; + values_ = Source.values_; + } + else { + // If we were a view, we will now be a copy. + if(!valuesCopied_) { + numRows_ = Source.numRows_; + numCols_ = Source.numCols_; + stride_ = Source.numRows_; + const OrdinalType newsize = stride_ * numCols_; + if(newsize > 0) { + values_ = new ScalarType[newsize]; + valuesCopied_ = true; + } + else { + values_ = 0; + } + } + // If we were a copy, we will stay a copy. + else { + if((Source.numRows_ <= stride_) && (Source.numCols_ == numCols_)) { // we don't need to reallocate + numRows_ = Source.numRows_; + numCols_ = Source.numCols_; + } + else { // we need to allocate more space (or less space) + deleteArrays(); + numRows_ = Source.numRows_; + numCols_ = Source.numCols_; + stride_ = Source.numRows_; + const OrdinalType newsize = stride_ * numCols_; + if(newsize > 0) { + values_ = new ScalarType[newsize]; + valuesCopied_ = true; + } + } + } + copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0, false); + } + return(*this); + } + + template + SerialDenseMatrix& SerialDenseMatrix::operator+= (const SerialDenseMatrix& Source ) + { + // Check for compatible dimensions + if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_)) + { + TEUCHOS_CHK_REF(*this); // Return *this without altering it. + } + copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0, 1.0); + return(*this); + } + + template + SerialDenseMatrix& SerialDenseMatrix::operator-= (const SerialDenseMatrix& Source ) + { + // Check for compatible dimensions + if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_)) + { + TEUCHOS_CHK_REF(*this); // Return *this without altering it. + } + copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0, -1.0); + return(*this); + } + + template + SerialDenseMatrix& SerialDenseMatrix::assign (const SerialDenseMatrix& Source) { + if(this == &Source) + return(*this); // Special case of source same as target + if((!valuesCopied_) && (!Source.valuesCopied_) && (values_ == Source.values_)) + return(*this); // Special case of both are views to same data. + + // Check for compatible dimensions + if ((numRows_ != Source.numRows_) || (numCols_ != Source.numCols_)) + { + TEUCHOS_CHK_REF(*this); // Return *this without altering it. + } + copyMat(Source.values_, Source.stride_, numRows_, numCols_, values_, stride_, 0, 0 ); + return(*this); + } + + //---------------------------------------------------------------------------------------------------- + // Accessor methods + //---------------------------------------------------------------------------------------------------- + + template + inline ScalarType& SerialDenseMatrix::operator () (OrdinalType rowIndex, OrdinalType colIndex) + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + checkIndex( rowIndex, colIndex ); +#endif + return(values_[colIndex * stride_ + rowIndex]); + } + + template + inline const ScalarType& SerialDenseMatrix::operator () (OrdinalType rowIndex, OrdinalType colIndex) const + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + checkIndex( rowIndex, colIndex ); +#endif + return(values_[colIndex * stride_ + rowIndex]); + } + + template + inline const ScalarType* SerialDenseMatrix::operator [] (OrdinalType colIndex) const + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + checkIndex( 0, colIndex ); +#endif + return(values_ + colIndex * stride_); + } + + template + inline ScalarType* SerialDenseMatrix::operator [] (OrdinalType colIndex) + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + checkIndex( 0, colIndex ); +#endif + return(values_ + colIndex * stride_); + } + + //---------------------------------------------------------------------------------------------------- + // Norm methods + //---------------------------------------------------------------------------------------------------- + + template + typename ScalarTraits::magnitudeType SerialDenseMatrix::normOne() const + { + OrdinalType i, j; + typename ScalarTraits::magnitudeType anorm = ScalarTraits::magnitude(ScalarTraits::zero()); + typename ScalarTraits::magnitudeType absSum = ScalarTraits::magnitude(ScalarTraits::zero()); + ScalarType* ptr; + for(j = 0; j < numCols_; j++) + { + ScalarType sum = 0; + ptr = values_ + j * stride_; + for(i = 0; i < numRows_; i++) + { + sum += ScalarTraits::magnitude(*ptr++); + } + absSum = ScalarTraits::magnitude(sum); + if(absSum > anorm) + { + anorm = absSum; + } + } + updateFlops(numRows_ * numCols_); + return(anorm); + } + + template + typename ScalarTraits::magnitudeType SerialDenseMatrix::normInf() const + { + OrdinalType i, j; + typename ScalarTraits::magnitudeType sum, anorm = ScalarTraits::magnitude(ScalarTraits::zero()); + + for (i = 0; i < numRows_; i++) { + sum = ScalarTraits::magnitude(ScalarTraits::zero()); + for (j=0; j< numCols_; j++) { + sum += ScalarTraits::magnitude(*(values_+i+j*stride_)); + } + anorm = TEUCHOS_MAX( anorm, sum ); + } + updateFlops(numRows_ * numCols_); + return(anorm); + } + + template + typename ScalarTraits::magnitudeType SerialDenseMatrix::normFrobenius() const + { + OrdinalType i, j; + typename ScalarTraits::magnitudeType anorm = ScalarTraits::magnitude(ScalarTraits::zero()); + for (j = 0; j < numCols_; j++) { + for (i = 0; i < numRows_; i++) { + anorm += ScalarTraits::magnitude(values_[i+j*stride_]*values_[i+j*stride_]); + } + } + anorm = ScalarTraits::magnitude(ScalarTraits::squareroot(anorm)); + updateFlops(numRows_ * numCols_); + return(anorm); + } + + //---------------------------------------------------------------------------------------------------- + // Comparison methods + //---------------------------------------------------------------------------------------------------- + + template + bool SerialDenseMatrix::operator== (const SerialDenseMatrix &Operand) + { + bool result = 1; + if((numRows_ != Operand.numRows_) || (numCols_ != Operand.numCols_)) + { + result = 0; + } + else + { + OrdinalType i, j; + for(i = 0; i < numRows_; i++) + { + for(j = 0; j < numCols_; j++) + { + if((*this)(i, j) != Operand(i, j)) + { + return 0; + } + } + } + } + return result; + } + + template + bool SerialDenseMatrix::operator!= (const SerialDenseMatrix &Operand) + { + return !((*this) == Operand); + } + + //---------------------------------------------------------------------------------------------------- + // Multiplication method + //---------------------------------------------------------------------------------------------------- + + template + int SerialDenseMatrix::scale( const ScalarType alpha ) + { + OrdinalType i, j; + ScalarType* ptr; + + for (j=0; j + int SerialDenseMatrix::scale( const SerialDenseMatrix& A ) + { + OrdinalType i, j; + ScalarType* ptr; + + // Check for compatible dimensions + if ((numRows_ != A.numRows_) || (numCols_ != A.numCols_)) + { + TEUCHOS_CHK_ERR(-1); // Return error + } + for (j=0; j + int SerialDenseMatrix::multiply(ETransp transa, ETransp transb, ScalarType alpha, const SerialDenseMatrix &A, const SerialDenseMatrix &B, ScalarType beta) + { + // Check for compatible dimensions + OrdinalType A_nrows = (ETranspChar[transa]!='N') ? A.numCols() : A.numRows(); + OrdinalType A_ncols = (ETranspChar[transa]!='N') ? A.numRows() : A.numCols(); + OrdinalType B_nrows = (ETranspChar[transb]!='N') ? B.numCols() : B.numRows(); + OrdinalType B_ncols = (ETranspChar[transb]!='N') ? B.numRows() : B.numCols(); + if ((numRows_ != A_nrows) || (A_ncols != B_nrows) || (numCols_ != B_ncols)) + { + TEUCHOS_CHK_ERR(-1); // Return error + } + // Call GEMM function + this->GEMM(transa, transb, numRows_, numCols_, A_ncols, alpha, A.values(), A.stride(), B.values(), B.stride(), beta, values_, stride_); + double nflops = 2 * numRows_; + nflops *= numCols_; + nflops *= A_ncols; + updateFlops(nflops); + return(0); + } + + + template + void SerialDenseMatrix::print(std::ostream& os) const + { + os << std::endl; + if(valuesCopied_) + os << "Values_copied : yes" << std::endl; + else + os << "Values_copied : no" << std::endl; + os << "Rows : " << numRows_ << std::endl; + os << "Columns : " << numCols_ << std::endl; + os << "LDA : " << stride_ << std::endl; + if(numRows_ == 0 || numCols_ == 0) { + os << "(matrix is empty, no values to display)" << std::endl; + } else { + for(OrdinalType i = 0; i < numRows_; i++) { + for(OrdinalType j = 0; j < numCols_; j++){ + os << (*this)(i,j) << " "; + } + os << std::endl; + } + } + } + + //---------------------------------------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------------------------------------- + + template + inline void SerialDenseMatrix::checkIndex( OrdinalType rowIndex, OrdinalType colIndex ) const { + TEST_FOR_EXCEPTION(rowIndex < 0 || rowIndex >= numRows_, std::out_of_range, + "SerialDenseMatrix::checkIndex: " + "Row index " << rowIndex << " out of range [0, "<< numRows_ << ")"); + TEST_FOR_EXCEPTION(colIndex < 0 || colIndex >= numCols_, std::out_of_range, + "SerialDenseMatrix::checkIndex: " + "Col index " << colIndex << " out of range [0, "<< numCols_ << ")"); + } + + template + void SerialDenseMatrix::deleteArrays(void) + { + if (valuesCopied_) + { + delete [] values_; + values_ = 0; + valuesCopied_ = false; + } + } + + template + void SerialDenseMatrix::copyMat(ScalarType* inputMatrix, OrdinalType strideInput, OrdinalType numRows, OrdinalType numCols, ScalarType* outputMatrix, OrdinalType strideOutput, OrdinalType startRow, OrdinalType startCol, ScalarType alpha) + { + OrdinalType i, j; + ScalarType* ptr1 = 0; + ScalarType* ptr2 = 0; + for(j = 0; j < numCols; j++) { + ptr1 = outputMatrix + (j * strideOutput); + ptr2 = inputMatrix + (j + startCol) * strideInput + startRow; + if (alpha != Teuchos::ScalarTraits::zero() ) { + for(i = 0; i < numRows; i++) + { + *ptr1++ += alpha*(*ptr2++); + } + } else { + for(i = 0; i < numRows; i++) + { + *ptr1++ = *ptr2++; + } + } + } + } + +} // namespace Teuchos + + +#endif /* _TEUCHOS_SERIALDENSEMATRIX_HPP_ */ diff --git a/fastlib/trilinos/include/Teuchos_SerialDenseVector.hpp b/fastlib/trilinos/include/Teuchos_SerialDenseVector.hpp new file mode 100644 index 0000000000..3691fc88ce --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_SerialDenseVector.hpp @@ -0,0 +1,287 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + + +#ifndef _TEUCHOS_SERIALDENSEVECTOR_HPP_ +#define _TEUCHOS_SERIALDENSEVECTOR_HPP_ + +/*! \file Teuchos_SerialDenseVector.hpp + \brief Templated serial dense std::vector class +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_Object.hpp" +#include "Teuchos_SerialDenseMatrix.hpp" + +/*! \class Teuchos::SerialDenseVector + \brief This class creates and provides basic support for dense vectors of templated type as a specialization of Teuchos::SerialDenseMatrix. Additional methods for the SerialDenseVector class, like mathematical methods, can be found documented in SerialDenseMatrix. +*/ +namespace Teuchos { + + template + class SerialDenseVector : public SerialDenseMatrix { + + public: + //! @name Constructor/Destructor methods. + //@{ + + //! Default Constructor + /*! Creates an empty std::vector of no length. The Sizing methods should be used to size this matrix. Values of this matrix should be set using the [] or the () operators. + */ + SerialDenseVector(); + + //! Shaped Constructor + /*! + \param length - Number of elements in this std::vector. + + Creates a shaped std::vector of length \c length. All values are initialized to zero. Values of this std::vector should be set using [] or the () operators. + */ + SerialDenseVector(OrdinalType length); + + //! Shaped Constructor with Values + /*! + \param CV - Enumerated type set to Teuchos::Copy or Teuchos::View. + \param values - Pointer to an array of ScalarType of the given \c length. + \param length - Length of std::vector to be constructed. + */ + SerialDenseVector(DataAccess CV, ScalarType* values, OrdinalType length); + + //! Copy Constructor + SerialDenseVector(const SerialDenseVector& Source); + + //! Destructor + virtual ~SerialDenseVector (); + //@} + + //! @name Sizing methods. + //@{ + + //! Size method for changing the size of a SerialDenseVector, initializing entries to zero. + /*! + \param length - The length of the new std::vector. + + This allows the user to define the length of a SerialDenseVector at any point. + This method can be called at any point after construction. Any values previously in + this object will be destroyed and the resized std::vector starts with all zero values. + */ + int size(OrdinalType length) {return(SerialDenseMatrix::shape(length, 1));} + + //! Resizing method for changing the size of a SerialDenseVector, keeping the entries. + /*! + \param length - The length of the new std::vector. + This allows the user to redefine the length of a SerialDenseVector at any point. + This method can be called at any point after construction. Any values previously in + this object will be copied to the resized std::vector. + */ + int resize(OrdinalType length) {return(SerialDenseMatrix::reshape(length, 1));} + //@} + + //! @name Comparison methods. + //@{ + //! Equality of two matrices. + /*! \return True if \e this std::vector and \c Operand are of the same length and have the same entries, else False will be returned. + */ + bool operator == (const SerialDenseVector &Operand); + + //! Inequality of two matrices. + /*! \return True if \e this std::vector and \c Operand are not of the same length or do not have the same entries, else False will be returned. + */ + bool operator != (const SerialDenseVector &Operand); + //@} + + //! @name Set methods. + //@{ + + //! Copies values from one std::vector to another. + /*! + The operator= copies the values from one existing SerialDenseVector to + another. If \c Source is a view (i.e. CV = Teuchos::View), then this + method will return a view. Otherwise, it will return a copy of \c Source. + \e this will be resized if it is not large enough to copy \c Source into. + */ + SerialDenseVector& operator = (const SerialDenseVector& Source); + //@} + + //! @name Accessor methods. + //@{ + //! Element access method (non-const). + /*! Returns the ith element if x(i) is specified, the expression x[i] will return the same element. + \return (*this)(index) + \warning The validity of \c index will only be checked if Teuchos is configured with --enable-teuchos-abc. + */ + ScalarType& operator () (OrdinalType index); + + //! Element access method (const). + /*! Returns the ith element if x(i) is specified, the expression x[i] will return the same element. + \return (*this)(index) + \warning The validity of \c index will only be checked if Teuchos is configured with --enable-teuchos-abc. + */ + const ScalarType& operator () (OrdinalType index) const; + + //! Element access method (non-const). + /*! Returns the ith element if x[i] is specified, the expression x(i) will return the same element. + \return (*this)[index] + \warning The validity of \c index will only be checked if Teuchos is configured with --enable-teuchos-abc. + */ + ScalarType& operator [] (OrdinalType index); + + //! Element access method (const). + /*! Returns the ith element if x[i] is specified, the expression x(i) will return the same element. + \return (*this)[index] + \warning The validity of \c index will only be checked if Teuchos is configured with --enable-teuchos-abc. + */ + const ScalarType& operator [] (OrdinalType index) const; + + //@} + + //! @name Attribute methods. + //@{ + //! Returns the length of this std::vector. + OrdinalType length() const {return(this->numRows_);} + //@} + + //! @name I/O methods. + //@{ + //! Print method. Define the behavior of the std::ostream << operator inherited from the Object class. + virtual void print(std::ostream& os) const; + //@} +}; + + template + SerialDenseVector::SerialDenseVector() : SerialDenseMatrix() {} + + template + SerialDenseVector::SerialDenseVector( OrdinalType length ) : SerialDenseMatrix( length, 1 ) {} + + template + SerialDenseVector::SerialDenseVector(DataAccess CV, ScalarType* values, OrdinalType length) : + SerialDenseMatrix( CV, values, length, length, 1 ) {} + + template + SerialDenseVector::SerialDenseVector(const SerialDenseVector &Source) : + SerialDenseMatrix( Source ) {} + + template + SerialDenseVector::~SerialDenseVector() {} + + template + SerialDenseVector& SerialDenseVector::operator = (const SerialDenseVector& Source) + { + SerialDenseMatrix::operator=(Source); + return(*this); + } + + template + bool SerialDenseVector::operator == (const SerialDenseVector &Operand) + { + bool result = 1; + if(this->numRows_ != Operand.numRows_) + { + result = 0; + } + else + { + OrdinalType i; + for(i = 0; i < this->numRows_; i++) { + if((*this)(i) != Operand(i)) + { + return 0; + } + } + } + return result; + } + + template + bool SerialDenseVector::operator != (const SerialDenseVector &Operand) + { + return !((*this)==Operand); + } + + template + void SerialDenseVector::print(std::ostream& os) const + { + os << std::endl; + if(this->valuesCopied_) + os << "Values_copied : yes" << std::endl; + else + os << "Values_copied : no" << std::endl; + os << "Length : " << this->numRows_ << std::endl; + if(this->numRows_ == 0) { + os << "(std::vector is empty, no values to display)" << std::endl; + } else { + for(OrdinalType i = 0; i < this->numRows_; i++) { + os << (*this)(i) << " "; + } + os << std::endl; + } + } + + //---------------------------------------------------------------------------------------------------- + // Accessor methods + //---------------------------------------------------------------------------------------------------- + + template + inline ScalarType& SerialDenseVector::operator () (OrdinalType index) + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + this->checkIndex( index ); +#endif + return(this->values_[index]); + } + + template + inline const ScalarType& SerialDenseVector::operator () (OrdinalType index) const + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + this->checkIndex( index ); +#endif + return(this->values_[index]); + } + + template + inline const ScalarType& SerialDenseVector::operator [] (OrdinalType index) const + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + this->checkIndex( index ); +#endif + return(this->values_[index]); + } + + template + inline ScalarType& SerialDenseVector::operator [] (OrdinalType index) + { +#ifdef HAVE_TEUCHOS_ARRAY_BOUNDSCHECK + this->checkIndex( index ); +#endif + return(this->values_[index]); + } + +} // namespace Teuchos + +#endif /* _TEUCHOS_SERIALDENSEVECTOR_HPP_ */ diff --git a/fastlib/trilinos/include/Teuchos_SerializationTraits.hpp b/fastlib/trilinos/include/Teuchos_SerializationTraits.hpp new file mode 100644 index 0000000000..23dbfa631d --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_SerializationTraits.hpp @@ -0,0 +1,216 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_SERIALIZATION_TRAITS_HPP +#define TEUCHOS_SERIALIZATION_TRAITS_HPP + +#include "Teuchos_ConfigDefs.hpp" + +namespace Teuchos { + +template +struct UndefinedSerializationTraits { + //! This function should not compile if there is an attempt to instantiate! + static inline T notDefined() {return(T::this_type_is_missing_a_specialization());} +}; + +/** \brief Serialization traits class for types that use value semantics. + * + * There are one of two modes associated with serialization. + * + * ToDo: Finish documenation! + */ +template +class SerializationTraits { +public: + + //! @name Seialization type selection + //@{ + + /** \brief Determines if the type supports direct serialization. */ + static const bool supportsDirectSerialization = false; + + //@} + + //! @name Direct serialization functions (not defined if supportsDirectSerialization==false) + //@{ + + /** \brief Return the number of bytes for count objects. */ + static Ordinal fromCountToDirectBytes(const Ordinal count) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Convert the pointer type to char*. */ + static char* convertToCharPtr( T* ptr ) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Convert the pointer type to const char*. */ + static const char* convertToCharPtr( const T* ptr ) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Return the number of objects for bytes of storage. */ + static Ordinal fromDirectBytesToCount(const Ordinal bytes) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Convert the pointer type from char*. */ + static T* convertFromCharPtr( char* ptr ) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Convert the pointer type from char*. */ + static const T* convertFromCharPtr( const char* ptr ) { UndefinedSerializationTraits::notDefined(); return 0; } + + //@} + + //! @name Indirect serialization functions (always defined and supported) + //@{ + + /** \brief Return the number of bytes for count objects. */ + static Ordinal fromCountToIndirectBytes(const Ordinal count) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Serialize to an indirect char[] buffer. + * + * \param count + * [in] The number of objects to serialize. + * \param buffer + * [in] The objects to serialize. + * \param bytes + * [in] Number of bytes in charBuffer[] + * \param charBuffer + * [out] Array (length bytes) containing the serialized objects. + * + * Preconditions:
      + *
    • bytes==fromCountToIndirectBytes(count) + *
    + */ + static void serialize( + const Ordinal count, const T buffer[], const Ordinal bytes, char charBuffer[] + ) + { UndefinedSerializationTraits::notDefined(); } + + /** \brief Return the number of objects for bytes of storage. */ + static Ordinal fromIndirectBytesToCount(const Ordinal bytes) { UndefinedSerializationTraits::notDefined(); return 0; } + + /** \brief Deserialize from an indirect char[] buffer. + * + * \param bytes + * [in] Number of bytes in charBuffer[] + * \param charBuffer + * [in] Array (length bytes) containing the serialized objects. + * \param count + * [in] The number of objects to deserialize. + * \param buffer + * [out] The deserialized objects. + + * Preconditions:
      + *
    • count==fromIndirectBytesToCount(bytes) + *
    + */ + static void deserialize( + const Ordinal bytes, const char charBuffer[], const Ordinal count, T buffer[] + ) + { UndefinedSerializationTraits::notDefined(); } + + //@} + +}; + +template +class DirectSerializationTraits { +public: + static const bool supportsDirectSerialization = true; + // Direct serialization + static Ordinal fromCountToDirectBytes(const Ordinal count) + { return sizeof(T)*count; } + static char* convertToCharPtr( T* ptr ) + { return reinterpret_cast(ptr); } + static const char* convertToCharPtr( const T* ptr ) + { return reinterpret_cast(ptr); } + static Ordinal fromDirectBytesToCount(const Ordinal count) + { return count/sizeof(T); } + static T* convertFromCharPtr( char* ptr ) + { return reinterpret_cast(ptr); } + static const T* convertFromCharPtr( const char* ptr ) + { return reinterpret_cast(ptr); } + // Indirect serialization + static Ordinal fromCountToIndirectBytes(const Ordinal count) + { return fromCountToDirectBytes(count); } + static void serialize( + const Ordinal count, const T buffer[], const Ordinal bytes, char charBuffer[] + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT(bytes!=fromCountToIndirectBytes(count)); +#endif + const char *_buffer = convertToCharPtr(buffer); + std::copy(_buffer,_buffer+bytes,charBuffer); + } + static Ordinal fromIndirectBytesToCount(const Ordinal bytes) + { return fromDirectBytesToCount(bytes); } + static void deserialize( + const Ordinal bytes, const char charBuffer[], const Ordinal count, T buffer[] + ) + { +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT(count!=fromIndirectBytesToCount(bytes)); +#endif + char *_buffer = convertToCharPtr(buffer); + std::copy(charBuffer,charBuffer+bytes,_buffer); + } +}; + +template +class SerializationTraits + : public DirectSerializationTraits +{}; + +template +class SerializationTraits + : public DirectSerializationTraits +{}; + +template +class SerializationTraits + : public DirectSerializationTraits +{}; + +template +class SerializationTraits + : public DirectSerializationTraits +{}; + +#if defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX) + +template +class SerializationTraits > + : public DirectSerializationTraits > +{}; + +template +class SerializationTraits > + : public DirectSerializationTraits > +{}; + +#endif // defined(HAVE_COMPLEX) && defined(HAVE_TEUCHOS_COMPLEX) + +} // namespace Teuchos + +#endif // TEUCHOS_SERIALIZATION_TRAITS_HPP diff --git a/fastlib/trilinos/include/Teuchos_SerializationTraitsHelpers.hpp b/fastlib/trilinos/include/Teuchos_SerializationTraitsHelpers.hpp new file mode 100644 index 0000000000..4ca71ac289 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_SerializationTraitsHelpers.hpp @@ -0,0 +1,311 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_SERIALIZATION_TRAITS_HELPERS_HPP +#define TEUCHOS_SERIALIZATION_TRAITS_HELPERS_HPP + +#include "Teuchos_SerializationTraits.hpp" + +namespace Teuchos { + +/** \brief Encapsulate how an array of non-const objects with value sematics + * is serialized into a char[] array. + */ +template +class ValueTypeSerializationBuffer { +public: + /** \brief Serialize to an internally stored char[] buffer. */ + ValueTypeSerializationBuffer( + const Ordinal count, T buffer[] + ); + /** \brief Deserialize from the interal char[] buffer back to the + * original T[] buffer. + */ + ~ValueTypeSerializationBuffer(); + /** \brief . */ + char* getCharBuffer() const; + /** \brief . */ + Ordinal getBytes() const; +private: + Ordinal count_; + T *buffer_; + Ordinal bytes_; + char *charBuffer_; + // Not defined and not to be called + ValueTypeSerializationBuffer(); + ValueTypeSerializationBuffer(const ValueTypeSerializationBuffer&); + ValueTypeSerializationBuffer& operator=(const ValueTypeSerializationBuffer&); +}; + +/** \brief Encapsulate how an array of const objects with value sematics is + * serialized into a const char[] array. + */ +template +class ConstValueTypeSerializationBuffer { +public: + /** \brief Serialize to an internally stored char[] buffer. */ + ConstValueTypeSerializationBuffer( + const Ordinal count, const T buffer[] + ); + /** \brief Deserialize from the interal char[] buffer back to the + * original T[] buffer. + */ + ~ConstValueTypeSerializationBuffer(); + /** \brief . */ + const char* getCharBuffer() const; + /** \brief . */ + Ordinal getBytes() const; +private: + Ordinal count_; + const T *buffer_; + Ordinal bytes_; + const char *charBuffer_; + // Not defined and not to be called + ConstValueTypeSerializationBuffer(); + ConstValueTypeSerializationBuffer(const ConstValueTypeSerializationBuffer&); + ConstValueTypeSerializationBuffer& operator=(const ConstValueTypeSerializationBuffer&); +}; + +/** \brief Encapsulate how an array of non-const serialized objects with value + * sematics stored in a char[] array is deserialized to a + * T[] array and then serialized back again. + */ +template +class ValueTypeDeserializationBuffer { +public: + /** \brief Serialize to an internally stored char[] buffer. */ + ValueTypeDeserializationBuffer( + const Ordinal bytes, char charBuffer[] + ); + /** \brief Deserialize from the interal char[] buffer back to the + * original T[] buffer. + */ + ~ValueTypeDeserializationBuffer(); + /** \brief . */ + T* getBuffer() const; + /** \brief . */ + Ordinal getCount() const; +private: + Ordinal bytes_; + char *charBuffer_; + Ordinal count_; + T *buffer_; + // Not defined and not to be called + ValueTypeDeserializationBuffer(); + ValueTypeDeserializationBuffer(const ValueTypeDeserializationBuffer&); + ValueTypeDeserializationBuffer& operator=(const ValueTypeDeserializationBuffer&); +}; + +/** \brief Encapsulate how an array of non-const serialized objects with value + * sematics stored in a char[] array is deserialized to a + * T[] array and then serialized back again. + */ +template +class ConstValueTypeDeserializationBuffer { +public: + /** \brief Serialize to an internally stored char[] buffer. */ + ConstValueTypeDeserializationBuffer( + const Ordinal bytes, const char charBuffer[] + ); + /** \brief Deserialize from the interal char[] buffer back to the + * original T[] buffer. + */ + ~ConstValueTypeDeserializationBuffer(); + /** \brief . */ + const T* getBuffer() const; + /** \brief . */ + Ordinal getCount() const; +private: + Ordinal bytes_; + const char *charBuffer_; + Ordinal count_; + const T *buffer_; + // Not defined and not to be called + ConstValueTypeDeserializationBuffer(); + ConstValueTypeDeserializationBuffer(const ConstValueTypeDeserializationBuffer&); + ConstValueTypeDeserializationBuffer& operator=(const ConstValueTypeDeserializationBuffer&); +}; + +// ///////////////////////////////////// +// Template implementations + +// +// ValueTypeSerializationBuffer +// +// ToDo: Update this implementation to handle objects with indirect +// serialization when needed! +// + +template +ValueTypeSerializationBuffer::ValueTypeSerializationBuffer( + const Ordinal count, T buffer[] + ) + :count_(count), buffer_(buffer) +{ + typedef SerializationTraits SerT; + bytes_ = SerT::fromCountToDirectBytes(count_); + charBuffer_ = SerT::convertToCharPtr(buffer_); + // ToDo: Handle indirect serailization! +} + +template +ValueTypeSerializationBuffer::~ValueTypeSerializationBuffer() +{ + // There is nothing to do since the type uses direct serialization! + // ToDo: Handle indirect serailization! +} + +template +char* ValueTypeSerializationBuffer::getCharBuffer() const +{ + return charBuffer_; +} + +template +Ordinal ValueTypeSerializationBuffer::getBytes() const +{ + return bytes_; +} + +// +// ConstValueTypeSerializationBuffer +// +// ToDo: Update this implementation to handle objects with indirect +// serialization when needed! +// + +template +ConstValueTypeSerializationBuffer::ConstValueTypeSerializationBuffer( + const Ordinal count, const T buffer[] + ) + :count_(count), buffer_(buffer) +{ + typedef SerializationTraits SerT; + bytes_ = SerT::fromCountToDirectBytes(count_); + charBuffer_ = SerT::convertToCharPtr(buffer_); + // ToDo: Handle indirect serailization! +} + +template +ConstValueTypeSerializationBuffer::~ConstValueTypeSerializationBuffer() +{ + // There is nothing to do since the type uses direct serialization! + // ToDo: Handle indirect serailization! +} + +template +const char* ConstValueTypeSerializationBuffer::getCharBuffer() const +{ + return charBuffer_; +} + +template +Ordinal ConstValueTypeSerializationBuffer::getBytes() const +{ + return bytes_; +} + +// +// ValueTypeDeserializationBuffer +// +// ToDo: Update this implementation to handle objects with indirect +// serialization when needed! +// + +template +ValueTypeDeserializationBuffer::ValueTypeDeserializationBuffer( + const Ordinal bytes, char charBuffer[] + ) + :bytes_(bytes), charBuffer_(charBuffer) +{ + typedef SerializationTraits SerT; + count_ = SerT::fromDirectBytesToCount(bytes_); + buffer_ = SerT::convertFromCharPtr(charBuffer_); + // ToDo: Handle indirect serailization! +} + +template +ValueTypeDeserializationBuffer::~ValueTypeDeserializationBuffer() +{ + // There is nothing to do since the type uses direct serialization! + // ToDo: Handle indirect serailization! +} + +template +T* ValueTypeDeserializationBuffer::getBuffer() const +{ + return buffer_; +} + +template +Ordinal ValueTypeDeserializationBuffer::getCount() const +{ + return count_; +} + +// +// ConstValueTypeDeserializationBuffer +// +// ToDo: Update this implementation to handle objects with indirect +// serialization when needed! +// + +template +ConstValueTypeDeserializationBuffer::ConstValueTypeDeserializationBuffer( + const Ordinal bytes, const char charBuffer[] + ) + :bytes_(bytes), charBuffer_(charBuffer) +{ + typedef SerializationTraits SerT; + count_ = SerT::fromDirectBytesToCount(bytes_); + buffer_ = SerT::convertFromCharPtr(charBuffer_); + // ToDo: Handle indirect serailization! +} + +template +ConstValueTypeDeserializationBuffer::~ConstValueTypeDeserializationBuffer() +{ + // There is nothing to do since the type uses direct serialization! + // ToDo: Handle indirect serailization! +} + +template +const T* ConstValueTypeDeserializationBuffer::getBuffer() const +{ + return buffer_; +} + +template +Ordinal ConstValueTypeDeserializationBuffer::getCount() const +{ + return count_; +} + +} // namespace Teuchos + +#endif // TEUCHOS_SERIALIZATION_TRAITS_HELPERS_HPP diff --git a/fastlib/trilinos/include/Teuchos_Serializer.hpp b/fastlib/trilinos/include/Teuchos_Serializer.hpp new file mode 100644 index 0000000000..02341db699 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Serializer.hpp @@ -0,0 +1,113 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_SERIALIZER_HPP +#define TEUCHOS_SERIALIZER_HPP + +#include "Teuchos_RCP.hpp" + +namespace Teuchos { + +/** \brief Strategy interface for the indirect serializing and deserializing + * objects of a given type handled using reference semantics. + * + * This interface serializes and serializes objects of type T to and + * from independent char[] buffer arrays. Direct serialization (i.e. + * just using reinterpret casts) is not possible using this interface. + */ +template +class Serializer { +public: + + /** \brief . */ + virtual ~Serializer() {} + + /** \brief Return an estimate for the maximum storage for count + * objects to be serialized. + */ + virtual Ordinal getBufferSize(const Ordinal count) const = 0; + + /** \brief Serialize an object to a char[] buffer. + * + * \param count + * [in] Number of objects to be serialized. + * \param objs + * [in] Array (length count) for the objects to be serialized. + * \param bytes + * [in] Length of the buffer charBuffer[] + * \param charBuffer + * [out] Array (length bytes) that contains the serialized objects. + * + * Preconditions:
      + *
    • count > 0 + *
    • objs != NULL + *
    • charBuffer != NULL + * bytes == getBufferSize(count) + *
    + */ + virtual void serialize( + const Ordinal count + ,const T * const objs[] + ,const Ordinal bytes + ,char charBuffer[] + ) const = 0; + + /** \brief Create an object of type T to be serialized into. + */ + virtual RCP createObj() const = 0; + + /** \brief Deserialize an object from a char[] buffer. + * + * \param bytes + * [in] Length of the buffer charBuffer[] + * \param charBuffer + * [in] Array (length bytes) that contains the serialized objects. + * \param count + * [in] Number of objects to be deserialized. + * \param objs + * [out] Array (length count) for the deserialized objects. + * + * Preconditions:
      + *
    • bytes > 0 + *
    • objs != NULL + *
    • charBuffer != NULL + * bytes == getBufferSize(count) + *
    + */ + virtual void deserialize( + const Ordinal bytes + ,const char charBuffer[] + ,const Ordinal count + ,T * const objs[] + ) const = 0; + +}; + +} // namespace Teuchos + +#endif // TEUCHOS_SERIALIZER_HPP diff --git a/fastlib/trilinos/include/Teuchos_SerializerHelpers.hpp b/fastlib/trilinos/include/Teuchos_SerializerHelpers.hpp new file mode 100644 index 0000000000..75794091dd --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_SerializerHelpers.hpp @@ -0,0 +1,337 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_SERIALIZER_HELPERS_HPP +#define TEUCHOS_SERIALIZER_HELPERS_HPP + +#include "Teuchos_Serializer.hpp" +#include "Teuchos_Array.hpp" + +namespace Teuchos { + +/** \brief Encapsulate how an array of non-const objects with reference + * sematics is serialized into a char[] array and deserialized again. + */ +template +class ReferenceTypeSerializationBuffer { +public: + /** \brief Serialize to an internally stored char[] buffer. */ + ReferenceTypeSerializationBuffer( + const Serializer &serializer + ,const Ordinal count, T*const buffer[] + ); + /** \brief Deserialize from the interal char[] buffer back to the + * original T*[] buffer. + */ + ~ReferenceTypeSerializationBuffer(); + /** \brief . */ + char* getCharBuffer() const; + /** \brief . */ + Ordinal getBytes() const; +private: + const Serializer &serializer_; + Ordinal count_; + T*const *buffer_; + Array charBuffer_; + // Not defined and not to be called + ReferenceTypeSerializationBuffer(); + ReferenceTypeSerializationBuffer(const ReferenceTypeSerializationBuffer&); + ReferenceTypeSerializationBuffer& operator=(const ReferenceTypeSerializationBuffer&); +}; + +/** \brief Encapsulate how an array of const objects with reference sematics + * is serialized into a char[] array. + */ +template +class ConstReferenceTypeSerializationBuffer { +public: + /** \brief Serialize to an internally stored char[] buffer. */ + ConstReferenceTypeSerializationBuffer( + const Serializer &serializer + ,const Ordinal count, const T*const buffer[] + ); + /** \brief Free the internal char[] buffer (no data to be written + * back). + */ + ~ConstReferenceTypeSerializationBuffer(); + /** \brief . */ + const char* getCharBuffer() const; + /** \brief . */ + Ordinal getBytes() const; +private: + const Serializer &serializer_; + Ordinal count_; + const T*const *buffer_; + Ordinal bytes_; + Array charBuffer_; + // Not defined and not to be called + ConstReferenceTypeSerializationBuffer(); + ConstReferenceTypeSerializationBuffer(const ConstReferenceTypeSerializationBuffer&); + ConstReferenceTypeSerializationBuffer& operator=(const ConstReferenceTypeSerializationBuffer&); +}; + +/** \brief Encapsulate how an array of non-const objects with reference + * sematics is deserialized from a char[] array and then serialized + * back into the char[] buffer again. + */ +template +class ReferenceTypeDeserializationBuffer { +public: + /** \brief Serialize to an internally stored T*[] buffer. */ + ReferenceTypeDeserializationBuffer( + const Serializer &serializer + ,const Ordinal bytes, char charBuffer[] + ); + /** \brief Reserialize back to the char[] buffer from the internal + * T*[] buffer. + */ + ~ReferenceTypeDeserializationBuffer(); + /** \brief . */ + T*const* getBuffer() const; + /** \brief . */ + Ordinal getCount() const; +private: + typedef Array > buffer_ptr_t; + typedef Array buffer_t; + const Serializer &serializer_; + Ordinal bytes_; + char *charBuffer_; + buffer_ptr_t buffer_ptr_; + buffer_t buffer_; + // Not defined and not to be called + ReferenceTypeDeserializationBuffer(); + ReferenceTypeDeserializationBuffer(const ReferenceTypeDeserializationBuffer&); + ReferenceTypeDeserializationBuffer& operator=(const ReferenceTypeDeserializationBuffer&); +}; + +/** \brief Encapsulate how an array of onst objects with reference sematics is + * deserialized from a char[] array with memory being automatically + * freed at destruction time. + */ +template +class ConstReferenceTypeDeserializationBuffer { +public: + /** \brief Serialize to an internally stored T*[] buffer. */ + ConstReferenceTypeDeserializationBuffer( + const Serializer &serializer + ,const Ordinal bytes, const char charBuffer[] + ); + /** \brief Reserialize back to the char[] buffer from the internal + * T*[] buffer. + */ + ~ConstReferenceTypeDeserializationBuffer(); + /** \brief . */ + const T*const* getBuffer() const; + /** \brief . */ + Ordinal getCount() const; +private: + typedef Array > buffer_ptr_t; + typedef Array buffer_t; + const Serializer &serializer_; + Ordinal bytes_; + const char *charBuffer_; + buffer_ptr_t buffer_ptr_; + buffer_t buffer_; + // Not defined and not to be called + ConstReferenceTypeDeserializationBuffer(); + ConstReferenceTypeDeserializationBuffer(const ConstReferenceTypeDeserializationBuffer&); + ConstReferenceTypeDeserializationBuffer& operator=(const ConstReferenceTypeDeserializationBuffer&); +}; + +// ///////////////////////////////////// +// Template implementations + +// +// ReferenceTypeSerializationBuffer +// + +template +ReferenceTypeSerializationBuffer::ReferenceTypeSerializationBuffer( + const Serializer &serializer + ,const Ordinal count, T*const buffer[] + ) + :serializer_(serializer), count_(count), buffer_(buffer) +{ + const Ordinal bytes = serializer_.getBufferSize(count_); + charBuffer_.resize(bytes); + serializer_.serialize(count_,buffer_,bytes,&charBuffer_[0]); +} + +template +ReferenceTypeSerializationBuffer::~ReferenceTypeSerializationBuffer() +{ + serializer_.deserialize(charBuffer_.size(),&charBuffer_[0],count_,buffer_); +} + +template +char* ReferenceTypeSerializationBuffer::getCharBuffer() const +{ + typedef ReferenceTypeSerializationBuffer* this_ptr_t; + return &(const_cast(this)->charBuffer_)[0]; + // The above const_cast is a better alternative to declaring charBuffer_ to + // be mutable, in my opinion. +} + +template +Ordinal ReferenceTypeSerializationBuffer::getBytes() const +{ + return charBuffer_.size(); +} + +// +// ConstReferenceTypeSerializationBuffer +// + +template +ConstReferenceTypeSerializationBuffer::ConstReferenceTypeSerializationBuffer( + const Serializer &serializer + ,const Ordinal count, const T*const buffer[] + ) + :serializer_(serializer), count_(count), buffer_(buffer) +{ + const Ordinal bytes = serializer_.getBufferSize(count_); + charBuffer_.resize(bytes); + serializer_.serialize(count_,buffer_,bytes,&charBuffer_[0]); +} + +template +ConstReferenceTypeSerializationBuffer::~ConstReferenceTypeSerializationBuffer() +{ + // No need to copy back from the char[] buffer! +} + +template +const char* ConstReferenceTypeSerializationBuffer::getCharBuffer() const +{ + return &charBuffer_[0]; +} + +template +Ordinal ConstReferenceTypeSerializationBuffer::getBytes() const +{ + return charBuffer_.size(); +} + +// +// ReferenceTypeDeserializationBuffer +// + +template +ReferenceTypeDeserializationBuffer::ReferenceTypeDeserializationBuffer( + const Serializer &serializer + ,const Ordinal bytes, char charBuffer[] + ) + :serializer_(serializer),bytes_(bytes),charBuffer_(charBuffer) +{ + const Ordinal extent = serializer_.getBufferSize(1); + const Ordinal count = bytes_ / extent; +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT( !( bytes_ % extent == 0 ) ); +#endif + buffer_ptr_.resize(count); + buffer_.resize(count); + for( int i = 0; i < count; ++i ) { + buffer_ptr_[i] = serializer_.createObj(); + buffer_[i] = &*buffer_ptr_[i]; + } + serializer_.deserialize( + bytes_,charBuffer_,count,&buffer_[0] + ); +} + +template +ReferenceTypeDeserializationBuffer::~ReferenceTypeDeserializationBuffer() +{ + serializer_.serialize( + buffer_.size(),&buffer_[0],bytes_,charBuffer_ + ); +} + +template +T*const* ReferenceTypeDeserializationBuffer::getBuffer() const +{ + typedef ReferenceTypeDeserializationBuffer* this_ptr_t; + return &(const_cast(this)->buffer_)[0]; + // The above const_cast is a better alternative to declaring buffer_ to be + // mutable, in my opinion. +} + +template +Ordinal ReferenceTypeDeserializationBuffer::getCount() const +{ + return buffer_.size(); +} + +// +// ConstReferenceTypeDeserializationBuffer +// + +template +ConstReferenceTypeDeserializationBuffer::ConstReferenceTypeDeserializationBuffer( + const Serializer &serializer + ,const Ordinal bytes, const char charBuffer[] + ) + :serializer_(serializer),bytes_(bytes),charBuffer_(charBuffer) +{ + const Ordinal extent = serializer_.getBufferSize(1); + const Ordinal count = bytes_ / extent; +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT( !( bytes_ % extent == 0 ) ); +#endif + buffer_ptr_.resize(count); + buffer_.resize(count); + for( int i = 0; i < count; ++i ) { + buffer_ptr_[i] = serializer_.createObj(); + buffer_[i] = &*buffer_ptr_[i]; + } + serializer_.deserialize( + bytes_,charBuffer_,count,&buffer_[0] + ); +} + +template +ConstReferenceTypeDeserializationBuffer::~ConstReferenceTypeDeserializationBuffer() +{ + // We don't need to serialized back into charBuffer_[] since it is constant! +} + +template +const T*const* ConstReferenceTypeDeserializationBuffer::getBuffer() const +{ + return &buffer_[0]; +} + +template +Ordinal ConstReferenceTypeDeserializationBuffer::getCount() const +{ + return buffer_.size(); +} + +} // namespace Teuchos + +#endif // TEUCHOS_SERIALIZER_HELPERS_HPP diff --git a/fastlib/trilinos/include/Teuchos_StandardCatchMacros.hpp b/fastlib/trilinos/include/Teuchos_StandardCatchMacros.hpp new file mode 100644 index 0000000000..138d4b5a87 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_StandardCatchMacros.hpp @@ -0,0 +1,92 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_STANDARD_CATCH_MACROS_HPP +#define TEUCHOS_STANDARD_CATCH_MACROS_HPP + +#include "Teuchos_GlobalMPISession.hpp" +#include "Teuchos_FancyOStream.hpp" +#include "Teuchos_TypeNameTraits.hpp" + +/** \brief Simple macro that catches and reports standard exceptions and other exceptions. + * + * \ingroup teuchos_language_support_grp + * + * This macro should be used to write simple main() program functions + * wrapped in a try statement as: + + \code + + int main(...) + { + bool verbose = true; + bool success = true; + try { + ... + } + TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose,std::cerr,success); + return ( success ? 0 : 1 ); + } + \endcode + */ +#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE,ERR_STREAM,SUCCESS_FLAG) \ + catch( const std::exception &excpt ) { \ + if((VERBOSE)) { \ + std::ostringstream oss; \ + oss \ + << "\np="<<::Teuchos::GlobalMPISession::getRank()<<": *** Caught standard std::exception of type \'" \ + <> members as attribute members for any class. +*/ + +#include "Teuchos_RCP.hpp" + +/** \brief Macro that adds <> members for a composition association. + * + * This form is for when the object being held will have const attributes + * the same as the this object. + * + * For example, if you want to include a <> association + * with an non-const object of type MyClass of the name my_object you + * would include the macro in the public section of YourClass + * declaration as follows: + * + \verbatim + class YourClass { + public: + STANDARD_COMPOSITION_MEMBERS( MyClass, my_object ); + }; + \endverbatim + * + * Note that the macro adds the following data member + * to the class declaration:
    + \verbatim + private: + Teuchos::RCP< TYPE > NAME_; + \endverbatim + * + * \ingroup StandardContainmentMacros_grp + */ +#define STANDARD_COMPOSITION_MEMBERS( TYPE, NAME ) \ + void set_ ## NAME (const Teuchos::RCP< TYPE >& NAME ) \ + { NAME ## _ = NAME ; } \ + Teuchos::RCP< TYPE > get_ ## NAME() const \ + { return NAME ## _; } \ + TYPE& NAME() \ + { return *NAME ## _; } \ + const TYPE& NAME() const \ + { return *NAME ## _; } \ +private: \ + Teuchos::RCP< TYPE > NAME ## _; \ +public: \ + typedef Teuchos::RCP< TYPE > NAME ## _ptr_t + +/** \breif Macro that adds <> members for a composition association. + * + * This form is for when the object being held will have non-const attributes + * irrespective of the const of this. + * + * For example, if you want to include a <> association + * with an non-const object of type MyClass of the name my_object you + * would include the macro in the public section of YourClass + * declaration as follows: + * + \verbatim + class YourClass { + public: + STANDARD_NONCONST_COMPOSITION_MEMBERS( MyClass, my_object ); + }; + \endverbatim + * + * Note that the macro adds the following data member + * to the class declaration:
    + \verbatim + private: + Teuchos::RCP< TYPE > NAME_; + \endverbatim + * + * \ingroup StandardContainmentMacros_grp + */ +#define STANDARD_NONCONST_COMPOSITION_MEMBERS( TYPE, NAME ) \ + void set_ ## NAME ( const Teuchos::RCP< TYPE >& NAME ) \ + { NAME ## _ = NAME ; } \ + Teuchos::RCP< TYPE > get_ ## NAME() const \ + { return NAME ## _; } \ + TYPE& NAME() const \ + { return *NAME ## _; } \ +private: \ + Teuchos::RCP< TYPE > NAME ## _; \ +public: \ + typedef Teuchos::RCP< TYPE > NAME ## _ptr_t + +/** \brief Macro that adds <> members for a composition association + * where the contained object is always constant. + * + * This form is for when the object being held will have const attributes + * irrespective of the const of this. + * + * For example, if you want to include a <> association + * with a const object of type MyClass of the name my_object you + * would include the macro in the public section of YourClass + * declaration as follows: + * + \verbatim + class YourClass { + public: + STANDARD_CONST_COMPOSITION_MEMBERS( MyClass, my_object ); + }; + \endverbatim + * + * Note that the macro adds the following data member + * to the class declaration:
    + \verbatim + private: + NAME_ptr_t NAME_; + \endverbatim + * + * \ingroup StandardContainmentMacros_grp + */ +#define STANDARD_CONST_COMPOSITION_MEMBERS( TYPE, NAME ) \ +public: \ + void set_ ## NAME ( const Teuchos::RCP< const TYPE >& NAME ) \ + { NAME ## _ = NAME ; } \ + Teuchos::RCP< const TYPE > get_ ## NAME() const \ + { return NAME ## _; } \ + const TYPE& NAME() const \ + { return *NAME ## _; } \ +private: \ + Teuchos::RCP< const TYPE > NAME ## _; \ +public: \ + typedef Teuchos::RCP< const TYPE > NAME ## _ptr_t + +#endif // TEUCHOS_STANDARD_COMPOSITION_MACROS_HPP diff --git a/fastlib/trilinos/include/Teuchos_StandardMemberCompositionMacros.hpp b/fastlib/trilinos/include/Teuchos_StandardMemberCompositionMacros.hpp new file mode 100644 index 0000000000..0628628ee0 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_StandardMemberCompositionMacros.hpp @@ -0,0 +1,87 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// //////////////////////////////////////////////////////////// +// Teuchos_StandardMemberCompositionMacros.hpp + +#ifndef TEUCHOS_STANDARD_MEMBER_COMPOSITION_MACROS_H +#define TEUCHOS_STANDARD_MEMBER_COMPOSITION_MACROS_H + +/*! \file Teuchos_StandardMemberCompositionMacros.hpp \brief Macro + that adds <> members as attribute members for any + class. +*/ +#include "Teuchos_ConfigDefs.hpp" + +/** \brief Macro that adds <> attributes to any class + * + * For example, if you want to include a <> attribute + * as a member object of type MyClass with the name my_attribute you + * would include the macro in the public section of YourClass + * declaration as follows: + \verbatim + + class YourClass { + public: + STANDARD_MEMBER_COMPOSITION_MEMBERS( MyClass, my_attribute ); + }; + \endverbatim + * This macro adds the following data member to the class declaration: + \verbatim + private: + MyClass my_attribute_; + \endverbatim + * and the following methods to your class declaration: + \verbatim + public: + void my_attribute( const My_Class & my_attribute ) + { my_attribute_ = my_attribute; } + const My_Class& my_attribute() const + { return my_attribute_; } + \endverbatim + * The advantage of using this type of declaration is that it saves + * you a lot of typing and space. Later if you need to override these + * operations you can just implement the member functions by hand. + */ +#define STANDARD_MEMBER_COMPOSITION_MEMBERS( TYPE, NAME )\ + void NAME ( const TYPE & NAME ) { NAME ## _ = NAME ; }\ + const TYPE& NAME() const { return NAME ## _; }\ +private:\ + TYPE NAME ## _;\ +public: \ + typedef ::Teuchos::DummyDummyClass NAME ## DummyDummyClass_t + +// Note: Above, the 'using Teuchos::DummyDummyClass' statement is just there +// to allow (and require) the macro use of the form: +// +// STANDARD_MEMBER_COMPOSITION_MEMBERS( MyClass, my_attribute ); +// +// which allows a semicolon at the end! +// + +#endif // TEUCHOS_STANDARD_MEMBER_COMPOSITION_MACROS_H diff --git a/fastlib/trilinos/include/Teuchos_StandardParameterEntryValidators.hpp b/fastlib/trilinos/include/Teuchos_StandardParameterEntryValidators.hpp new file mode 100644 index 0000000000..99a34cb252 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_StandardParameterEntryValidators.hpp @@ -0,0 +1,1143 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_STANDARD_PARAMETER_ENTRY_VALIDATORS_H +#define TEUCHOS_STANDARD_PARAMETER_ENTRY_VALIDATORS_H + +#include "Teuchos_ParameterEntryValidator.hpp" +#include "Teuchos_ParameterList.hpp" +#include "Teuchos_ParameterListExceptions.hpp" +#include "Teuchos_VerbosityLevel.hpp" +#include "Teuchos_Array.hpp" +#include "Teuchos_StrUtils.hpp" +#include "Teuchos_TypeNameTraits.hpp" + + +namespace Teuchos { + + +/** \brief Standard implementation of a ParameterEntryValidator that maps from + * a list of strings to some integral type value. + * + * Objects of this type are meant to be used as both abstract objects passed + * to Teuchos::ParameterList objects to be used to validate parameter + * types and values, and to be used by the code that reads parameter values. + * Having a single definition for the types of valids input and outputs for a + * parameter value makes it easier to write error free validated code. + */ +template +class StringToIntegralParameterEntryValidator : public ParameterEntryValidator { +public: + + /** \name Constructors */ + //@{ + + /** \brief Construct with a mapping from strings to ordinals 0 to + *
    n-1
    . + * + * \param strings + * [in] Array of unique std::string names. + * \param defaultParameterName + * [in] The default name of the parameter (used in error messages) + */ + StringToIntegralParameterEntryValidator( + Array const& strings, + std::string const& defaultParameterName + ); + + /** \brief Construct with a mapping from strings to aribitrary typed + * integral values. + * + * \param strings + * [in] Array of unique std::string names. + * \param integralValues + * [in] Array that gives the integral values associated with + * strings[] + * \param defaultParameterName + * [in] The default name of the parameter (used in error messages) + * + * Preconditions:
      + *
    • strings.size() == integralValues.size() + *
    + */ + StringToIntegralParameterEntryValidator( + Array const& strings, + Array const& integralValues, + std::string const& defaultParameterName + ); + + /** \brief Construct with a mapping from strings (with documentation) to + * aribitrary typed integral values. + * + * \param strings + * [in] Array of unique std::string names. + * \param stringsDocs + * [in] Array of documentation strings for each std::string value. + * \param integralValues + * [in] Array that gives the integral values associated with + * strings[] + * \param defaultParameterName + * [in] The default name of the parameter (used in error messages) + * + * Preconditions:
      + *
    • strings.size() == stringDocs.size() + *
    • strings.size() == integralValues.size() + *
    + */ + StringToIntegralParameterEntryValidator( + Array const& strings, + Array const& stringsDocs, + Array const& integralValues, + std::string const& defaultParameterName + ); + + //@} + + /** \name Local non-virtual validated lookup functions */ + //@{ + + /** \brief Perform a mapping from a std::string value to its integral value. + * + * \param str [in] String that is being used to lookup the corresponding + * integral value. + * \param paramName + * [in] Optional name that will be used to generate error messages. + * + * If the std::string name str does not exist, the an std::exception will be + * thrown with a very descriptive error message. + */ + IntegralType getIntegralValue( + const std::string &str, const std::string ¶mName = "", + const std::string &sublistName = "" + ) const; + + /** \brief Perform a mapping from a std::string value embedded in a + * ParameterEntry object and return its associated integral value. + * + * \param entry + * [in] The std::string entry. + * \param paramName + * [in] Optional name that will be used to generate error messages. + * \param sublistName + * [in] The name of the sublist. + * \param activeQuery + * [in] If true, then this lookup will be recored as an active query + * which will turn the isUsed bool to true. + */ + IntegralType getIntegralValue( + const ParameterEntry &entry, const std::string ¶mName = "", + const std::string &sublistName = "", const bool activeQuery = true + ) const; + + /** \brief Get and validate a std::string value embedded in a + * ParameterEntry object. + * + * + * \param entry + * [in] The std::string entry. + * \param paramName + * [in] Optional name that will be used to generate error messages. + * \param sublistName + * [in] The name of the sublist. + * \param activeQuery + * [in] If true, then this lookup will be recored as an active query + * which will turn the isUsed bool to true. + */ + std::string getStringValue( + const ParameterEntry &entry, const std::string ¶mName = "", + const std::string &sublistName = "", const bool activeQuery = true + ) const; + + /** \brief Lookup a parameter from a parameter list, perform a mapping from + * a std::string value embedded in the ParameterEntry object and return + * its associated integral value. + */ + IntegralType getIntegralValue( + ParameterList ¶mList, const std::string ¶mName, + const std::string &defaultValue + ) const; + + /** \brief Lookup a parameter from a parameter list, validate the std::string + * value, and return the std::string value. + */ + std::string getStringValue( + ParameterList ¶mList, const std::string ¶mName, + const std::string &defaultValue + ) const; + + /** \brief Validate the std::string and pass it on.. + * + * \param str [in] String that is being used to lookup the corresponding + * integral value. + * \param name [in] Optional name that will be used to generate error messages. + * + * If the std::string name str does not exist, the an std::exception will be + * thrown with a very descriptive error message. + */ + std::string validateString( + const std::string &str, const std::string ¶mName = "", + const std::string &sublistName = "" + ) const; + + //@} + + /** \name Overridden from ParameterEntryValidator */ + //@{ + + /** \brief . */ + void printDoc( + std::string const& docString, + std::ostream & out + ) const; + + /** \brief . */ + Teuchos::RCP > + validStringValues() const; + + /** \brief . */ + void validate( + ParameterEntry const& entry, + std::string const& paramName, + std::string const& sublistName + ) const; + + //@} + +private: + + typedef std::map map_t; + std::string defaultParameterName_; + std::string validValues_; + RCP > validStringValues_; + RCP > validStringValuesDocs_; + map_t map_; + + void setValidValues( + Array const& strings, + Array const* stringsDocs = NULL + ); + + // Not defined and not to be called. + StringToIntegralParameterEntryValidator(); + +}; + + +/** \brief Nonmember constructor (see implementation). + * + * \relates StringToIntegralParameterEntryValidator + */ +template +RCP > +stringToIntegralParameterEntryValidator( + Array const& strings, + std::string const& defaultParameterName + ); + + +/** \brief Nonmember constructor (see implementation). + * + * \relates StringToIntegralParameterEntryValidator + */ +template +RCP > +stringToIntegralParameterEntryValidator( + Array const& strings, + Array const& integralValues, + std::string const& defaultParameterName + ); + + +/** \brief Nonmember constructor (see implementation). + * + * \relates StringToIntegralParameterEntryValidator + */ +template +RCP > +stringToIntegralParameterEntryValidator( + Array const& strings, + Array const& stringsDocs, + Array const& integralValues, + std::string const& defaultParameterName + ); + + +/** \brief Set up a std::string parameter that will use an embedded validator to + * allow the extraction of an integral value. + * + * The function getIntegralValue() can then be used to extract the + * integral value of the std::string parameter. In this case, the integral value + * return will just be the zero-based index of the std::string value in the list + * strings. + * + * \relates ParameterList + */ +template +void setStringToIntegralParameter( + std::string const& paramName, + std::string const& defaultValue, + std::string const& docString, + Array const& strings, + ParameterList * paramList + ); + + +/** \brief Set up a std::string parameter that will use an embedded validator to + * allow the extraction of an integral value from a list of integral values. + * + * The function getIntegralValue() can then be used to extract the + * integral value of the std::string parameter. In this case, the integral value + * return will just be the zero-based index of the std::string value in the list + * strings. + * + * \relates ParameterList + */ +template +void setStringToIntegralParameter( + std::string const& paramName, + std::string const& defaultValue, + std::string const& docString, + Array const& strings, + Array const& integralValues, + ParameterList * paramList + ); + + +/** \brief Set up a std::string parameter with documentation strings for each valid + * value that will use an embedded validator to allow the extraction of an + * integral value from a list of integral values. + * + * The function getIntegralValue() can then be used to extract the + * integral value of the std::string parameter. In this case, the integral value + * return will just be the zero-based index of the std::string value in the list + * strings. + * + * \relates ParameterList + */ +template +void setStringToIntegralParameter( + std::string const& paramName, + std::string const& defaultValue, + std::string const& docString, + Array const& strings, + Array const& stringsDocs, + Array const& integralValues, + ParameterList * paramList + ); + + +/** \brief Get an integral value for a parameter that is assumed to already be set. + * + * This function does a dynamic cast to get the underlying valiator of type + * StringToIntegralParameterEntryValidator. If this dynamic + * cast failes then an Exceptions::InvalidParameterType std::exception is + * thrown with an excellent error message. + * + * \relates ParameterList + */ +template +IntegralType getIntegralValue( + ParameterList const& paramList, std::string const& paramName + ); + + +/** \brief Get a std::string value for a parameter that is assumed to already be set. + * + * This function does a dynamic cast to get the underlying valiator of type + * StringToIntegralParameterEntryValidator. The default type + * for IntegralValue is int. If this dynamic cast failes then an + * Exceptions::InvalidParameterType std::exception is thrown with an + * excellent error message. + * + * \relates ParameterList + */ +template +std::string getStringValue( + ParameterList const& paramList, std::string const& paramName + ); + + +/** \brief Get a StringToIntegralParameterEntryValidator object out of + * a ParameterEntry object. + * + * This function with thrown of the validator does not exist. + */ +template +RCP > +getStringToIntegralParameterEntryValidator( + ParameterEntry const& entry, ParameterList const& paramList, + std::string const& paramName + ); + + +/** \brief Return the std::string name of the verbosity level as it is accepted by the + * verbosity level parameter. + * + * \relates EVerbosityLevel + */ +std::string getVerbosityLevelParameterValueName( + const EVerbosityLevel verbLevel + ); + + +/** \brief Return a validator for EVerbosityLevel. + * + * \relates EVerbosityLevel + */ +RCP > +verbosityLevelParameterEntryValidator(std::string const& defaultParameterName); + + +/** \brief Standard implementation of a ParameterEntryValidator that accepts + * numbers from a number of different formats and converts them to numbers in + * another format. + * + * Objects of this type are meant to be used as both abstract objects passed + * to Teuchos::ParameterList objects to be used to validate parameter + * types and values, and to be used by the code that reads parameter values. + * Having a single definition for the types of valids input and outputs for a + * parameter value makes it easier to write error-free validated code. + */ +class AnyNumberParameterEntryValidator : public ParameterEntryValidator { +public: + + /** \name Public types */ + //@{ + + /** \brief Determines what type is the preferred type. */ + enum EPreferredType { PREFER_INT, PREFER_DOUBLE, PREFER_STRING }; + + + /** \brief Determines the types that are accepted. */ + class AcceptedTypes { + public: + /** \brief Allow all types or not on construction. */ + AcceptedTypes( bool allowAllTypesByDefault = true ) + :allowInt_(allowAllTypesByDefault),allowDouble_(allowAllTypesByDefault), + allowString_(allowAllTypesByDefault) + {} + /** \brief Set allow an int value or not */ + AcceptedTypes& allowInt( bool _allowInt ) + { allowInt_ = _allowInt; return *this; } + /** \brief Set allow a double value or not */ + AcceptedTypes& allowDouble( bool _allowDouble ) + { allowDouble_ = _allowDouble; return *this; } + /** \brief Set allow an std::string value or not */ + AcceptedTypes& allowString( bool _allowString ) + { allowString_ = _allowString; return *this; } + /** \brief Allow an int value? */ + bool allowInt() const { return allowInt_; } + /** \brief Allow an double value? */ + bool allowDouble() const { return allowDouble_; } + /** \brief Allow an std::string value? */ + bool allowString() const { return allowString_; } + private: + bool allowInt_; + bool allowDouble_; + bool allowString_; + }; + + + + //@} + + /** \name Constructors */ + //@{ + + /** \brief Construct with a preferrded type of double and accept all + * types. + */ + AnyNumberParameterEntryValidator(); + + /** \brief Construct with allowed input and output types and the preferred + * type. + * + * \param preferredType + * [in] Determines the preferred type. This enum value is used to + * set the default value in the override validateAndModify(). + * \param acceptedType + * [in] Determines the types that are allowed in the parameter list. + */ + AnyNumberParameterEntryValidator( + EPreferredType const preferredType, + AcceptedTypes const& acceptedTypes + ); + + //@} + + /** \name Local non-virtual validated lookup functions */ + //@{ + + /** \brief Get an integer value from a parameter entry. */ + int getInt( + const ParameterEntry &entry, const std::string ¶mName = "", + const std::string &sublistName = "", const bool activeQuery = true + ) const; + + /** \brief Get a double value from a parameter entry. */ + double getDouble( + const ParameterEntry &entry, const std::string ¶mName = "", + const std::string &sublistName = "", const bool activeQuery = true + ) const; + + /** \brief Get a std::string value from a parameter entry. */ + std::string getString( + const ParameterEntry &entry, const std::string ¶mName = "", + const std::string &sublistName = "", const bool activeQuery = true + ) const; + + /** \brief Lookup parameter from a parameter list and return as an int + * value. + */ + int getInt( + ParameterList ¶mList, const std::string ¶mName, + const int defaultValue + ) const; + + /** \brief Lookup parameter from a parameter list and return as an double + * value. + */ + double getDouble( + ParameterList ¶mList, const std::string ¶mName, + const double defaultValue + ) const; + + /** \brief Lookup parameter from a parameter list and return as an std::string + * value. + */ + std::string getString( + ParameterList ¶mList, const std::string ¶mName, + const std::string &defaultValue + ) const; + + //@} + + /** \name Overridden from ParameterEntryValidator */ + //@{ + + /** \brief . */ + void printDoc( + std::string const& docString, + std::ostream & out + ) const; + + /** \brief . */ + Teuchos::RCP > + validStringValues() const; + + /** \brief . */ + void validate( + ParameterEntry const& entry, + std::string const& paramName, + std::string const& sublistName + ) const; + + /** \brief . */ + void validateAndModify( + std::string const& paramName, + std::string const& sublistName, + ParameterEntry * entry + ) const; + + //@} + +private: + + // //////////////////////////// + // Private data members + + EPreferredType preferredType_; + const AcceptedTypes acceptedTypes_; + std::string acceptedTypesString_; + + // //////////////////////////// + // Private member functions + + void finishInitialization(); + + void throwTypeError( + ParameterEntry const& entry, + std::string const& paramName, + std::string const& sublistName + ) const; + +}; + + +// Nonmember helper functions + + +/** \brief Nonmember constructor AnyNumberParameterEntryValidator. + * + * \relates AnyNumberParameterEntryValidator + */ +RCP +anyNumberParameterEntryValidator( + AnyNumberParameterEntryValidator::EPreferredType const preferredType, + AnyNumberParameterEntryValidator::AcceptedTypes const& acceptedTypes + ); + + +/** \brief Set an integer parameter that allows for (nearly) any input + * parameter type that is convertible to an int. + * + * \relates ParameterList + */ +void setIntParameter( + std::string const& paramName, + int const value, std::string const& docString, + ParameterList *paramList, + AnyNumberParameterEntryValidator::AcceptedTypes const& acceptedTypes + = AnyNumberParameterEntryValidator::AcceptedTypes() + ); + + +/** \brief Set an double parameter that allows for (nearly) any input + * parameter type that is convertible to a double. + * + * \relates ParameterList + */ +void setDoubleParameter( + std::string const& paramName, + double const& value, std::string const& docString, + ParameterList *paramList, + AnyNumberParameterEntryValidator::AcceptedTypes const& acceptedTypes + = AnyNumberParameterEntryValidator::AcceptedTypes() + ); + + +/** \brief Set an numeric parameter preferred as a std::string that allows for + * (nearly) any input parameter type that is convertible to a std::string. + * + * \relates ParameterList + */ +void setNumericStringParameter( + std::string const& paramName, + std::string const& value, std::string const& docString, + ParameterList *paramList, + AnyNumberParameterEntryValidator::AcceptedTypes const& acceptedTypes + = AnyNumberParameterEntryValidator::AcceptedTypes() + ); + + +/** \brief Get an integer parameter. + * + * If the underlying parameter type is already an integer, then all is good. + * However, if it is not, then a AnyNumberParameterEntryValidator object is + * looked for to extract the type correctly. If no validator is attached to + * the entry, then a new AnyNumberParameterEntryValidator object will be + * created that that will allow the conversion from any supported type. + * + * The parameter must exist or an Exceptions::InvalidParameterName + * object will be thrown. The parameters type must be acceptable, or an + * Exceptions::InvalidParameterType object will be thown. + * + * \relates ParameterList + */ +int getIntParameter( + ParameterList const& paramList, std::string const& paramName + ); + + +/** \brief Get double integer parameter. + * + * If the underlying parameter type is already a double, then all is good. + * However, if it is not, then a AnyNumberParameterEntryValidator object is + * looked for to extract the type correctly. If no validator is attached to + * the entry, then a new AnyNumberParameterEntryValidator object will be + * created that that will allow the conversion from any supported type. + * + * The parameter must exist or an Exceptions::InvalidParameterName + * object will be thrown. The parameters type must be acceptable, or an + * Exceptions::InvalidParameterType object will be thown. + * + * \relates ParameterList + */ +double getDoubleParameter( + ParameterList const& paramList, + std::string const& paramName + ); + + +/** \brief Get std::string numeric parameter. + * + * If the underlying parameter type is already a std::string, then all is good. + * However, if it is not, then a AnyNumberParameterEntryValidator object is + * looked for to extract the type correctly. If no validator is attached to + * the entry, then a new AnyNumberParameterEntryValidator object will be + * created that that will allow the conversion from any supported type. + * + * The parameter must exist or an Exceptions::InvalidParameterName + * object will be thrown. The parameters type must be acceptable, or an + * Exceptions::InvalidParameterType object will be thown. + * + * \relates ParameterList + */ +std::string getNumericStringParameter( + ParameterList const& paramList, + std::string const& paramName + ); + + +// /////////////////////////// +// Implementations + + +// +// StringToIntegralParameterEntryValidator +// + + +// Constructors + + +template +StringToIntegralParameterEntryValidator::StringToIntegralParameterEntryValidator( + Array const& strings, std::string const& defaultParameterName + ) + :defaultParameterName_(defaultParameterName) +{ + typedef typename map_t::value_type val_t; + for( int i = 0; i < static_cast(strings.size()); ++i ) { + const bool unique = map_.insert( val_t( strings[i], i ) ).second; + TEST_FOR_EXCEPTION( + !unique, std::logic_error + ,"Error, the std::string \"" << strings[i] << "\" is a duplicate for parameter \"" + << defaultParameterName_ << "\"." + ); + } + setValidValues(strings); +} + + +template +StringToIntegralParameterEntryValidator::StringToIntegralParameterEntryValidator( + Array const& strings, Array const& integralValues + ,std::string const& defaultParameterName + ) + :defaultParameterName_(defaultParameterName) +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT( strings.size() != integralValues.size() ); +#endif + typedef typename map_t::value_type val_t; + for( int i = 0; i < static_cast(strings.size()); ++i ) { + const bool unique = map_.insert( val_t( strings[i], integralValues[i] ) ).second; + TEST_FOR_EXCEPTION( + !unique, std::logic_error + ,"Error, the std::string \"" << strings[i] << "\" is a duplicate for parameter \"" + << defaultParameterName_ << "\"" + ); + } + setValidValues(strings); +} + + +template +StringToIntegralParameterEntryValidator::StringToIntegralParameterEntryValidator( + Array const& strings + ,Array const& stringsDocs + ,Array const& integralValues + ,std::string const& defaultParameterName + ) + :defaultParameterName_(defaultParameterName) +{ +#ifdef TEUCHOS_DEBUG + TEST_FOR_EXCEPT( strings.size() != stringsDocs.size() ); + TEST_FOR_EXCEPT( strings.size() != integralValues.size() ); +#endif + typedef typename map_t::value_type val_t; + for( int i = 0; i < static_cast(strings.size()); ++i ) { + const bool unique = map_.insert( val_t( strings[i], integralValues[i] ) ).second; + TEST_FOR_EXCEPTION( + !unique, std::logic_error + ,"Error, the std::string \"" << strings[i] << "\" is a duplicate for parameter \"" + << defaultParameterName_ << "\"" + ); + } + setValidValues(strings,&stringsDocs); +} + + +// Lookup functions + + +template +IntegralType +StringToIntegralParameterEntryValidator::getIntegralValue( + const std::string &str, const std::string ¶mName + ,const std::string &sublistName + ) const +{ + typename map_t::const_iterator itr = map_.find(str); + TEST_FOR_EXCEPTION_PURE_MSG( + itr == map_.end(), Exceptions::InvalidParameterValue + ,"Error, the value \"" << str << "\" is not recognized for the parameter \"" + << ( paramName.length() ? paramName : defaultParameterName_ ) << "\"" + << "\nin the sublist \"" << sublistName << "\"." + << "\n\nValid values include:" + << "\n {\n" + << validValues_ + << " }" + ); + return (*itr).second; +} + + +template +IntegralType +StringToIntegralParameterEntryValidator::getIntegralValue( + const ParameterEntry &entry, const std::string ¶mName + ,const std::string &sublistName, const bool activeQuery + ) const +{ + const bool validType = ( entry.getAny(activeQuery).type() == typeid(std::string) ); + TEST_FOR_EXCEPTION_PURE_MSG( + !validType, Exceptions::InvalidParameterType + ,"Error, the parameter {paramName=\""<<(paramName.length()?paramName:defaultParameterName_) + << "\",type=\""<(entry.getAny(activeQuery)); // This cast should not fail! + return getIntegralValue(strValue,paramName,sublistName); // This will validate the value and throw! +} + + +template +std::string +StringToIntegralParameterEntryValidator::getStringValue( + const ParameterEntry &entry, const std::string ¶mName + ,const std::string &sublistName, const bool activeQuery + ) const +{ + // Validate the parameter's type and value + this->getIntegralValue(entry,paramName,sublistName,activeQuery); + // Return the std::string value which is now validated! + return any_cast(entry.getAny(activeQuery)); // This cast should not fail! +} + + +template +IntegralType +StringToIntegralParameterEntryValidator::getIntegralValue( + ParameterList ¶mList, const std::string ¶mName + ,const std::string &defaultValue + ) const +{ + const std::string + &strValue = paramList.get(paramName,defaultValue); + return getIntegralValue(strValue,paramName,paramList.name()); +} + + +template +std::string +StringToIntegralParameterEntryValidator::getStringValue( + ParameterList ¶mList, const std::string ¶mName + ,const std::string &defaultValue + ) const +{ + const std::string + &strValue = paramList.get(paramName,defaultValue); + getIntegralValue(strValue,paramName,paramList.name()); // Validate! + return strValue; +} + + +template +std::string +StringToIntegralParameterEntryValidator::validateString( + const std::string &str, const std::string ¶mName + ,const std::string &sublistName + ) const +{ + getIntegralValue(str,paramName,sublistName); // Validate! + return str; +} + + +// Overridden from ParameterEntryValidator + + +template +void StringToIntegralParameterEntryValidator::printDoc( + std::string const& docString + ,std::ostream & out + ) const +{ + StrUtils::printLines(out,"# ",docString); + out << "# Valid std::string values:\n"; + out << "# {\n"; + if(validStringValuesDocs_.get()) { + for( int i = 0; i < static_cast(validStringValues_->size()); ++i ) { + out << "# \"" << (*validStringValues_)[i] << "\"\n"; + StrUtils::printLines(out,"# ",(*validStringValuesDocs_)[i] ); + } + } + else { + StrUtils::printLines(out,"# ",validValues_); + // Note: Above validValues_ has for initial spaces already so indent should + // be correct! + } + out << "# }\n"; +} + + +template +Teuchos::RCP > +StringToIntegralParameterEntryValidator::validStringValues() const +{ + return validStringValues_; +} + + +template +void StringToIntegralParameterEntryValidator::validate( + ParameterEntry const& entry + ,std::string const& paramName + ,std::string const& sublistName + ) const +{ + this->getIntegralValue(entry,paramName,sublistName,false); +} + + +// private + + +template +void StringToIntegralParameterEntryValidator::setValidValues( + Array const& strings + ,Array const* stringsDocs + ) +{ + validStringValues_ = rcp(new Array(strings)); + if(stringsDocs) + validStringValuesDocs_ = rcp(new Array(*stringsDocs)); + // Here I build the list of valid values in the same order as passed in by + // the client! + std::ostringstream oss; + typename map_t::const_iterator itr = map_.begin(); + for( int i = 0; i < static_cast(strings.size()); ++i ) { + oss << " \""< +inline +Teuchos::RCP > +Teuchos::stringToIntegralParameterEntryValidator( + Array const& strings, + std::string const& defaultParameterName + ) +{ + return rcp( + new StringToIntegralParameterEntryValidator( + strings, defaultParameterName + ) + ); +} + + +template +inline +Teuchos::RCP > +Teuchos::stringToIntegralParameterEntryValidator( + Array const& strings, + Array const& integralValues, + std::string const& defaultParameterName + ) +{ + return rcp( + new StringToIntegralParameterEntryValidator( + strings, integralValues, defaultParameterName + ) + ); +} + + +template +inline +Teuchos::RCP< Teuchos::StringToIntegralParameterEntryValidator > +Teuchos::stringToIntegralParameterEntryValidator( + Array const& strings, + Array const& stringsDocs, + Array const& integralValues, + std::string const& defaultParameterName + ) +{ + return rcp( + new StringToIntegralParameterEntryValidator( + strings, stringsDocs, integralValues, defaultParameterName + ) + ); +} + + +template +void Teuchos::setStringToIntegralParameter( + std::string const& paramName, + std::string const& defaultValue, + std::string const& docString, + Array const& strings, + ParameterList * paramList + ) +{ + TEST_FOR_EXCEPT(0==paramList); + paramList->set( + paramName, defaultValue, docString, + stringToIntegralParameterEntryValidator( + strings, paramName + ) + ); +} + + +template +void Teuchos::setStringToIntegralParameter( + std::string const& paramName, + std::string const& defaultValue, + std::string const& docString, + Array const& strings, + Array const& integralValues, + ParameterList * paramList + ) +{ + TEST_FOR_EXCEPT(0==paramList); + paramList->set( + paramName, defaultValue, docString, + stringToIntegralParameterEntryValidator( + strings, integralValues, paramName + ) + ); +} + + +template +void Teuchos::setStringToIntegralParameter( + std::string const& paramName, + std::string const& defaultValue, + std::string const& docString, + Array const& strings, + Array const& stringsDocs, + Array const& integralValues, + ParameterList * paramList + ) + +{ + TEST_FOR_EXCEPT(0==paramList); + paramList->set( + paramName, defaultValue, docString, + stringToIntegralParameterEntryValidator( + strings, stringsDocs, integralValues, paramName + ) + ); +} + + +template +IntegralType Teuchos::getIntegralValue( + ParameterList const& paramList, std::string const& paramName + ) +{ + const ParameterEntry &entry = paramList.getEntry(paramName); + RCP > + integralValidator = getStringToIntegralParameterEntryValidator( + entry, paramList, paramName + ); + return integralValidator->getIntegralValue( + entry, paramName, paramList.name(), true + ); +} + + +template +std::string Teuchos::getStringValue( + ParameterList const& paramList, std::string const& paramName + ) +{ + const ParameterEntry &entry = paramList.getEntry(paramName); + RCP > + integralValidator = getStringToIntegralParameterEntryValidator( + entry, paramList, paramName + ); + return integralValidator->getStringValue( + entry, paramName, paramList.name(), true + ); +} + + +template +Teuchos::RCP > +Teuchos::getStringToIntegralParameterEntryValidator( + ParameterEntry const& entry, ParameterList const& paramList, + std::string const& paramName + ) +{ + RCP + validator = entry.validator(); + TEST_FOR_EXCEPTION_PURE_MSG( + is_null(validator), Exceptions::InvalidParameterType, + "Error! The parameter \""<::name()<<"\"!" + ); + RCP > + integralValidator + = + rcp_dynamic_cast >( + validator + ); + TEST_FOR_EXCEPTION_PURE_MSG( + is_null(integralValidator), Exceptions::InvalidParameterType, + "Error! The parameter \""< >::name()<<"\"\n" + "but the contained validator type is \""< readFile(std::istream& is, char comment); + + /** \brief Split an input std::string that contains newlines into an array + of strings, one for each line */ + static Array splitIntoLines(const std::string& input); + + /** \brief Tokenize a file into whitespace-delimited tokens */ + static Array > tokenizeFile(std::istream& is, char comment); + + /** \brief Read a single line into a std::string */ + static bool readLine(std::istream& is, std::string& line); + + static Array stringTokenizer(const std::string& str); + + static Array getTokensPlusWhitespace(const std::string& str); + + static std::string reassembleFromTokens(const Array& tokens, int iStart=0); + + static void splitList(const std::string& bigstring, Array& elements); + + static int findNextWhitespace(const std::string& str, int offset); + + static int findNextNonWhitespace(const std::string& str, int offset); + + + static std::string varSubstitute(const std::string& rawLine, + const std::string& varName, + const std::string& varValue); + + static std::string varTableSubstitute(const std::string& rawLine, + const Array& varNames, + const Array& varValues); + + static std::string envSubstitute(const std::string& line); + + /** \brief Find the substring before a specified substring. For example, + * before("abcdefghij", "gh") returns "abcdef". */ + static std::string before(const std::string& str, const std::string& sub); + + /** \brief Find the substring before a specified character. For example, + * before("abcdefghij", 'g') returns "abcdef". */ + static std::string before(const std::string& str, char sub); + + /** \brief Find the substring after a specified substring. For example, + * before("abcdefghij", "gh") returns "ij". */ + static std::string after(const std::string& str, const std::string& sub); + + /** \brief Find the position at which a substring first occurs. For example, + * find("abcdefghij", "gh") returns 6. */ + static int find(const std::string& str, const std::string& sub); + + /** \brief Returns true if a std::string consists entirely of whitespace */ + static bool isWhite(const std::string& str); + + /** \brief Convert unprintable non-null characters to whitespace */ + static std::string fixUnprintableCharacters(const std::string& str); + + /** \brief Returns true if a std::string has any non-whitespace */ + static bool isNonWhite(const std::string& str) {return !isWhite(str);} + + /** \brief Returns the std::string between two delimiting strings, and returns + * by reference the strings before and after the delimiters. + * + * For example, between("abcdefghij", "c", "g", front, back) + * returns "def" and sets front to "ab", back to "hij". */ + static std::string between(const std::string& str, const std::string& begin, + const std::string& end, std::string& front, std::string& back); + + /** \brief Returns the substring between two positions. + * + * For example, subString("abcdefghij", 2, 5) returns "cde". */ + static std::string subString(const std::string& str, int begin, int end); + + static std::string readFromStream(std::istream& is); + + /** \brief Converts a std::string to all upper case */ + static std::string allCaps(const std::string& str); + + /** \brief Returns the double value of a std::string. */ + static double atof(const std::string& str); + + /** \brief Returns the int value of a std::string. */ + static int atoi(const std::string& str); + + /** \brief Print lines with prefix first. */ + static std::ostream& printLines( + std::ostream &os + ,const std::string &linePrefix + ,const std::string &lines + ); + + }; + +} + +#endif diff --git a/fastlib/trilinos/include/Teuchos_StringInputSource.hpp b/fastlib/trilinos/include/Teuchos_StringInputSource.hpp new file mode 100644 index 0000000000..d777ba1293 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_StringInputSource.hpp @@ -0,0 +1,68 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef Teuchos_STRINGINPUTSOURCE_H +#define Teuchos_STRINGINPUTSOURCE_H + +/*! \file Teuchos_StringInputSource.hpp + \brief Definition of XMLInputSource derived class for reading XML from + a std::string +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_XMLInputSource.hpp" + + +namespace Teuchos +{ + + using std::string; + + /** \ingroup XML + * \brief Instantiation of XMLInputSource class for reading XML from a std::string + */ + class StringInputSource : public XMLInputSource + { + public: + /** \brief Constructor */ + StringInputSource(const std::string& text); + + /** \brief Destructor */ + virtual ~StringInputSource(){;} + + /** \brief Create a StringInputStream */ + virtual RCP stream() const; + + private: + std::string text_; + }; + + +} +#endif + diff --git a/fastlib/trilinos/include/Teuchos_StringInputStream.hpp b/fastlib/trilinos/include/Teuchos_StringInputStream.hpp new file mode 100644 index 0000000000..ca66d22757 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_StringInputStream.hpp @@ -0,0 +1,73 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_STRINGINPUTSTREAM_H +#define TEUCHOS_STRINGINPUTSTREAM_H + +/*! \file Teuchos_StringInputStream.hpp + \brief Definition of XMLInputStream derived class for reading XML from a std::string +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_XMLInputStream.hpp" + + +namespace Teuchos +{ + using std::string; + + /** + * \brief Instantiation of XMLInputStream for reading an entire document from a std::string + * + * This is a low-level object and should not be needed at the user level. + * FileInputSource is the user-level object. + */ + + class StringInputStream : public XMLInputStream + { + public: + + //! Construct with the std::string from which data will be read + StringInputStream(const std::string& text) + : XMLInputStream(), text_(text), pos_(0) {;} + + //! Destructor + virtual ~StringInputStream() {;} + + //! Read up to maxToRead bytes + virtual unsigned int readBytes(unsigned char* const toFill, + const unsigned int maxToRead); + + private: + std::string text_; + unsigned int pos_; + }; + +} +#endif + diff --git a/fastlib/trilinos/include/Teuchos_StringToIntMap.hpp b/fastlib/trilinos/include/Teuchos_StringToIntMap.hpp new file mode 100644 index 0000000000..4befd961b9 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_StringToIntMap.hpp @@ -0,0 +1,151 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_STRING_TO_INT_MAP_HPP +#define TEUCHOS_STRING_TO_INT_MAP_HPP + +#include "Teuchos_TestForException.hpp" + +namespace Teuchos { + +/** \brief Map a std::string to an enumeration. + * + * The purpose of this class is to simplify mapping a standard std::string + * to an integer which can be interpreted as an enumeration. + * + * Here is an example of its use. + \verbatim + + const int n_opt = 3; + enum MyOptEnum { + OPT_ONE + ,OPT_TWO + ,OPT_THREE + }; // NOTE: Must be 0, 1,..., n_opt - 1 + const char* MyOptStrings[n_opt] = { + "OPT_ONE + ,"OPT_TWO" + ,"OPT_THREE" + }; // NOTE: parallels enums in MyOptEnum + StringToIntMap my_enum_map( "opt_map", n_opt, NyOptStrings ); + ... + switch( my_enum_map.get("OPT_ONE") ) { + case OPT_ONE: + // do stuff + case OPT_TWO: + // do stuff + case OPT_THREE: + // do stuff + default: + // ??? + } + + \endverbatim + * + * The number of strings passed to the constructor must equal the number of + * options in the enumeration. If there are duplicate strings + * (capitalization concidered) then the std::exception AlreadyExists is + * throw. If a std::string that was not passed in the constructor if given to + * operator()( const std::string& str ) then the std::exception + * DoesNotExist is thrown. + * + * In the constructor, defaultGroupName is used in error messages in + * the exceptions thrown to help make since out of the message. + * + * The default constructor is not defined and not to be called. + */ +class StringToIntMap { +public: + + /** \brief . */ + class AlreadyExists : public std::logic_error + {public: AlreadyExists(const std::string& what_arg) : std::logic_error(what_arg) {}}; + + /** \brief . */ + class DoesNotExist : public std::logic_error + {public: DoesNotExist(const std::string& what_arg) : std::logic_error(what_arg) {}}; + + /** \brief . */ + StringToIntMap( const std::string& defaultGroupName, int n, const char* strings[] ); + + /** \brief . */ + int get( const std::string& option, const std::string& groupName = "" ) const; + + /** \brief . */ + template + EnumType get( const std::string& option, const std::string& groupName = "" ) const; + + /** \brief . */ + const std::string& defaultGroupName() const; + +private: + + typedef std::map< std::string, int > map_t; // all share implementation. + std::string defaultGroupName_; + map_t map_; + + std::string validSelections() const; + + // not defined and not to be called. + StringToIntMap(); + +}; // end class StringToIntMap + +/** \brief Nonmember get function. + * \relates StringToIntMap + */ +template +inline +EnumType get( + StringToIntMap const& theMap + ,std::string const& option + ,std::string const& groupName = "" + ) +{ + return static_cast(theMap.get(option,groupName)); +} + +// //////////////////////////////////////////// +// Inline declarations + +template +inline +EnumType StringToIntMap::get( const std::string& option, const std::string& groupName ) const +{ + return static_cast(get(option,groupName)); +} + +inline +const std::string& StringToIntMap::defaultGroupName() const +{ + return defaultGroupName_; +} + +} // end namespace Teuchos + +#endif // TEUCHOS_STRING_TO_INT_MAP_HPP diff --git a/fastlib/trilinos/include/Teuchos_TableColumn.hpp b/fastlib/trilinos/include/Teuchos_TableColumn.hpp new file mode 100644 index 0000000000..b308eee73e --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_TableColumn.hpp @@ -0,0 +1,78 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_TABLECOLUMN_H +#define TEUCHOS_TABLECOLUMN_H + +/** \file Teuchos_TableColumn.hpp + \brief A column of TableEntry objects + */ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_TableEntry.hpp" +#include "Teuchos_Array.hpp" + +namespace Teuchos +{ + /** + * + * KL 30 Apr 2006 -- initial design. + */ + class TableColumn + { + public: + /** \brief Empty ctor */ + TableColumn() : data_() {;} + + /** \brief Form a column of std::string entries */ + TableColumn(const Array& vals); + + /** \brief Form a column of double entries */ + TableColumn(const Array& vals, int precision); + + /** \brief Form a column of compound entries written as "first(second)" */ + TableColumn(const Array& first, const Array& second, + int precision, + bool spaceBeforeParentheses); + + /** */ + int numRows() const {return data_.size();} + + /** */ + void addEntry(const RCP& entry); + + /** */ + const RCP& entry(int i) const {return data_[i];} + + private: + Array > data_; + }; + + +} +#endif diff --git a/fastlib/trilinos/include/Teuchos_TableEntry.hpp b/fastlib/trilinos/include/Teuchos_TableEntry.hpp new file mode 100644 index 0000000000..44c31236d2 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_TableEntry.hpp @@ -0,0 +1,163 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_TABLEENTRY_H +#define TEUCHOS_TABLEENTRY_H + +/** \file Teuchos_TableEntry.hpp + \brief Base class for representing compound entries in a printed + * table of data. + * "Compound" means that each entry may be some aggregation + * of more than one item, + * for example a timer together with a number of calls, or a + * value together with its estimated measurement error. + */ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_RCP.hpp" +#include "Teuchos_Array.hpp" +#include + +namespace Teuchos +{ + /** + * \brief An entry, perhaps compound, to be written into a table. + * + * KL 30 Apr 2006 -- initial design. Can you say overengineering?? + * The complexity is to support a nice interface for pair entries + * such as time/numCalls. + */ + class TableEntry + { + public: + /** \brief Empty ctor. */ + TableEntry() {} + + /** \brief virtual dtor */ + virtual ~TableEntry() {} + + /** \brief Return a std::string representation of this entry */ + virtual std::string toString() const = 0 ; + + /** \brief Return a std::string representation of this entry, + * truncated if necessary to fit within the given column width. + * + * \param maxWidth [in] the maximum width of the std::string form. Larger + * strings must be truncated in a subclass-dependent way. + * \return the std::string, truncated if necessary + */ + virtual std::string toChoppedString(int maxWidth) const ; + + protected: + }; + + + /** + * \brief A table entry that is a simple double-precision number + */ + class DoubleEntry : public TableEntry + { + public: + /** \brief Construct with a value + * and a precision */ + DoubleEntry(const double& value, int precision); + + /** \brief Write the specified entry to a std::string */ + virtual std::string toString() const ; + + private: + double data_; + int precision_; + }; + + + /** + * \brief A table entry that is a simple integer + */ + class IntEntry : public TableEntry + { + public: + /** \brief Construct with a value */ + IntEntry(int value); + + /** \brief Write the specified entry to a std::string */ + virtual std::string toString() const ; + + private: + int data_; + }; + + + /** + * \brief A table entry that is a simple std::string + */ + class StringEntry : public TableEntry + { + public: + /** \brief Construct with a value */ + StringEntry(std::string value); + + /** \brief Write the specified entry to a std::string */ + virtual std::string toString() const ; + + private: + std::string data_; + }; + + /** + * \brief An entry containing two subentries, with the second + * to be written in parentheses after the first. For example, + * \code + * 1.23(456) + * \endcode + * The two subentries can be any type of data, each represented + * with a TableEntry derived type. + */ + class CompoundEntryWithParentheses : public TableEntry + { + public: + /** \brief */ + CompoundEntryWithParentheses(const RCP& first, + const RCP& second, + bool spaceBeforeParens=true); + + /** \brief Write the specified entry to a std::string */ + virtual std::string toString() const ; + + private: + RCP first_; + RCP second_; + bool spaceBeforeParens_; + }; + + + + + +} +#endif diff --git a/fastlib/trilinos/include/Teuchos_TableFormat.hpp b/fastlib/trilinos/include/Teuchos_TableFormat.hpp new file mode 100644 index 0000000000..d568ef0765 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_TableFormat.hpp @@ -0,0 +1,171 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_TABLEFORMAT_H +#define TEUCHOS_TABLEFORMAT_H + +/*! \file Teuchos_TableFormat.hpp + \brief Provides utilities for formatting tabular output +*/ + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_TableColumn.hpp" +#include + +namespace Teuchos +{ + +/** \brief Encapsulation of formatting specifications for writing data + * in a clean tabular form. + * + * Note: it is left to the programmer to avoid invalid settings such as + * negative column spaces, zero page widths, and other such potentially + * bad things. + * + * KL 30 Apr 2006 -- initial design. + */ +class TableFormat +{ +public: + /** \brief Construct with a header and default format settings */ + TableFormat() + : pageWidth_(80), precision_(4), columnSpacing_(4), + maxNameSize_(40), columnWidths_(), lineInterval_(10) + {} + + /** \brief Get the maximum number of characters per line. + * Default is 80. */ + int pageWidth() const {return pageWidth_;} + + /** \brief Get the precision for writing doubles. + * Default is 4. */ + int precision() const {return precision_;} + + /** \brief Get the number of characters to be left as blank + * spaces in each column. Default is 4. */ + int columnSpacing() const {return columnSpacing_;} + + /** \brief Set the number of characters on a line. + * This quantity can be updated within the const + * method writeWholeTables() */ + void setPageWidth(int pw) const {pageWidth_ = pw;} + + /** \brief Set the precision for writing doubles */ + void setPrecision(int p) {precision_ = p;} + + /** \brief Set the number of characters to be left as blank spaces in each column */ + void setColumnSpacing(int columnSpacing) {columnSpacing_ = columnSpacing;} + + /** \brief Set the interval at which a horizontal line will be written between + * rows. + * + * \break lineInterval [in] the number of rows between each horizontal line + */ + void setRowsBetweenLines(int lineInterval) {lineInterval_=lineInterval;} + + /** \brief Return a horizontal line in dashes "----" + * the width of the page. + * + * Originally called hbar, but changed to avoid + * possible confusion for physicists expecting hbar() to return + * \f$1.05457168e-34\f$ :-). */ + std::string thinline() const ; + + /** \brief Return a thick horizontal line in equal signs "====" the + * width of the page */ + std::string thickline() const ; + + /** \brief Return a std::string full of blanks up to the requested size */ + std::string blanks(int size) const ; + + /** \brief Computes the column width required to write all values + * to the required precision. + * + * \param name [in] the title of the column + * \param column [in] the column data + * + * Postcondition: colString.size()==values.size() + */ + int computeRequiredColumnWidth(const std::string& name, + const TableColumn& column) const ; + + /** \brief Set the column widths to be used for subsequent rows */ + void setColumnWidths(const Array& colWidths) + {columnWidths_ = colWidths;} + + /** \brief Write the row of entries. + * + * \param out [in/out] the output stream to which the row will be written + * \param entries [in] the data to be written into this row. Each array + * element is the entry for a column on this row. + */ + void writeRow( + std::ostream& out, + const Array >& entries + ) const; + + /** \brief Write the row of entries. + * + * \param out [in/out] the output stream to which the row will be written + * \param columns [in] the columns of data from which this row is to be sliced + * \param rowIndex [in] the index into the columns used to obtain the values for + * this row + */ + void writeRow( + std::ostream& out, + int rowIndex, + const Array& columns + ) const; + + /** \brief . */ + void writeWholeTable( + std::ostream& out, + const std::string& tableTitle, + const Array& columnNames, + const Array& columns + ) const ; + +protected: + + int defaultColumnWidth() const {return 20;} + +private: + + mutable int pageWidth_; + int precision_; + int columnSpacing_; + int maxNameSize_; + Array columnWidths_; + int lineInterval_; +}; + + +} // namespace Teuchos + + +#endif diff --git a/fastlib/trilinos/include/Teuchos_TestForException.hpp b/fastlib/trilinos/include/Teuchos_TestForException.hpp new file mode 100644 index 0000000000..72dd61f71b --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_TestForException.hpp @@ -0,0 +1,222 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_TEST_FOR_EXCEPTION_H +#define TEUCHOS_TEST_FOR_EXCEPTION_H + +/*! \file Teuchos_TestForException.hpp +\brief Macro for throwing an exception with breakpointing to ease debugging. +*/ + +#include "Teuchos_TypeNameTraits.hpp" + +/*! \defgroup TestForException_grp Utility code for throwing exceptions and setting breakpoints. +\ingroup teuchos_language_support_grp +*/ +//@{ + +/** \brief Increment the throw number. */ +void TestForException_incrThrowNumber(); + +/** \brief Increment the throw number. */ +int TestForException_getThrowNumber(); + +/** \brief The only purpose for this function is to set a breakpoint. */ +void TestForException_break( const std::string &msg ); + +/** \brief Macro for throwing an exception with breakpointing to ease debugging + * + * @param throw_exception_test + * [in] Test for when to throw the exception. This can and + * should be an expression that may mean something to the user. + * The text verbatim of this expression is included in the + * formed error string. + * @param Exception + * [in] This should be the name of an exception class. The + * only requirement for this class is that it have a constructor + * that accepts an std::string object (as all of the standard + * exception classes do). + * @param msg [in] This is any expression that can be included in an + * output stream operation. This is useful when buinding + * error messages on the fly. Note that the code in this + * argument only gets evaluated if throw_exception_test + * evaluates to true when an exception is throw. + * + * The way that this macro is intended to be used is to + * call it in the source code like a function. For example, + * suppose that in a piece of code in the file my_source_file.cpp + * that the exception std::out_of_range is thrown if n > 100. + * To use the macro, the source code would contain (at line 225 + * for instance): + \verbatim + + TEST_FOR_EXCEPTION( n > 100, std::out_of_range + , "Error, n = " << n << is bad" ); + \endverbatim + * When the program runs and with n = 125 > 100 for instance, + * the std::out_of_range exception would be thrown with the + * error message: + \verbatim + + /home/bob/project/src/my_source_file.cpp:225: n > 100: Error, n = 125 is bad + \endverbatim + * + * In order to debug this, simply open your debugger (gdb for instance), + * set a break point at my_soure_file.cpp:225 and then set the condition + * to break for n > 100 (e.g. in gdb the command + * is cond break_point_number n > 100 and then run the + * program. The program should stop a the point in the source file + * right where the exception will be thrown at but before the exception + * is thrown. Try not to use expression for throw_exception_test that + * includes virtual function calls, etc. as most debuggers will not be able to check + * these types of conditions in order to stop at a breakpoint. For example, + * instead of: + \verbatim + + TEST_FOR_EXCEPTION( obj1->val() > obj2->val(), std::logic_error, "Oh no!" ); + \endverbatim + * try: + \verbatim + + double obj1_val = obj1->val(), obj2_val = obj2->val(); + TEST_FOR_EXCEPTION( obj1_val > obj2_val, std::logic_error, "Oh no!" ); + \endverbatim + * If the developer goes to the line in the source file that is contained + * in the error message of the exception thrown, he/she will see the + * underlying condition. + * + * As an alternative, you can set a breakpoint for any exception thrown + * by setting a breakpoint in the function ThrowException_break(). + */ +#define TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg) \ +{ \ + const bool throw_exception = (throw_exception_test); \ + if(throw_exception) { \ + TestForException_incrThrowNumber(); \ + std::ostringstream omsg; \ + omsg \ + << __FILE__ << ":" << __LINE__ << ":\n\n" \ + << "Throw number = " << TestForException_getThrowNumber() << "\n\n" \ + << "Throw test that evaluated to true: "#throw_exception_test << "\n\n" \ + << msg; \ + const std::string &omsgstr = omsg.str(); \ + TestForException_break(omsgstr); \ + throw Exception(omsgstr); \ + } \ +} + +/** \brief Macro for throwing an exception with breakpointing to ease debugging + * + * This macro is equivalent to the TEST_FOR_EXCEPTION() macro except + * the file name, line number, and test condition are not printed. + */ +#define TEST_FOR_EXCEPTION_PURE_MSG(throw_exception_test,Exception,msg) \ +{ \ + const bool throw_exception = (throw_exception_test); \ + if(throw_exception) { \ + TestForException_incrThrowNumber(); \ + std::ostringstream omsg; \ + omsg << msg; \ + omsg << "\n\nThrow number = " << TestForException_getThrowNumber() << "\n\n"; \ + const std::string &omsgstr = omsg.str(); \ + TestForException_break(omsgstr); \ + throw Exception(omsgstr); \ + } \ +} + +/** \brief This macro is designed to be a short version of + * TEST_FOR_EXCEPTION() that is easier to call. + * + * @param throw_exception_test + * [in] Test for when to throw the exception. This can and + * should be an expression that may mean something to the user. + * The text verbatim of this expression is included in the + * formed error string. + * + * \note The exception thrown is std::logic_error. + */ +#define TEST_FOR_EXCEPT(throw_exception_test) \ + TEST_FOR_EXCEPTION(throw_exception_test,std::logic_error,"Error!") + +/** \brief This macro is the same as TEST_FOR_EXCEPTION() except that the + * exception will be caught, the message printed, and then rethrown. + * + * @param throw_exception_test + * [in] See TEST_FOR_EXCEPTION(). + * @param Exception + * [in] See TEST_FOR_EXCEPTION(). + * @param msg [in] See TEST_FOR_EXCEPTION(). + * @param out_ptr + * [in] If out_ptr!=NULL then *out_ptr will receive + * a printout of a line of output that gives the exception type and + * the error message that is generated. + */ +#define TEST_FOR_EXCEPTION_PRINT(throw_exception_test,Exception,msg,out_ptr) \ +try { \ + TEST_FOR_EXCEPTION(throw_exception_test,Exception,msg); \ +} \ +catch(const std::exception &except) { \ + std::ostream *l_out_ptr = (out_ptr); \ + if(l_out_ptr) { \ + *l_out_ptr \ + << "\nThorwing an std::exception of type \'"<TEST_FOR_EXCEPT() except that the + * exception will be caught, the message printed, and then rethrown. + * + * @param throw_exception_test + * [in] See TEST_FOR_EXCEPT(). + * @param out_ptr + * [in] If out_ptr!=NULL then *out_ptr will receive + * a printout of a line of output that gives the exception type and + * the error message that is generated. + */ +#define TEST_FOR_EXCEPT_PRINT(throw_exception_test,out_ptr) \ + TEST_FOR_EXCEPTION_PRINT(throw_exception_test,std::logic_error,"Error!",out_ptr) + + +/** \brief This macro intercepts an exception, prints a standardized message including + * the current filename and line number, and then throws the exception up the stack + * @param exc [in] the exception that has been caught + */ +#define TEUCHOS_TRACE(exc)\ +{ \ + std::ostringstream omsg; \ + omsg << exc.what() << std::endl \ + << "caught in " << __FILE__ << ":" << __LINE__ << std::endl ; \ + throw std::runtime_error(omsg.str()); \ +} + + +//@} + +#endif // TEUCHOS_TEST_FOR_EXCEPTION_H diff --git a/fastlib/trilinos/include/Teuchos_Time.hpp b/fastlib/trilinos/include/Teuchos_Time.hpp new file mode 100644 index 0000000000..4f36b12060 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_Time.hpp @@ -0,0 +1,131 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +// Kris +// 07.08.03 -- Move into Teuchos package/namespace + +#ifndef _TEUCHOS_TIME_HPP_ +#define _TEUCHOS_TIME_HPP_ + +/*! \file Teuchos_Time.hpp + \brief Basic wall-clock timer class +*/ + +#include "Teuchos_ConfigDefs.hpp" + +#include +#ifdef HAVE_MPI +#include "mpi.h" +#else +#ifndef ICL +#include +#ifndef MINGW +#include +#endif +#endif +#endif + +namespace Teuchos +{ + + /** \brief Basic wall-clock timer class. + * + * To time a section of code, place it in between calls to start() and stop(). + * + * \note For std::exception safety and correct behavior in reentrant code, this class should + * generally be used only through the Teuchos::TimeMonitor mechanism. + * + */ + + /* ADDITIONAL COMMENTS: + * Initial version by Mike Heroux and Kris Kampshoff. + * Modified as follows by Kevin Long, 9/29/03: + *
      + *
    • There is no need to define explicit copy ctor and dtor for this class. + *
    • The wallTime() method returns the same value for every instance of this class, so + * it would be best to make it a static method. + *
    • Removed the communicator data member. Cross-processor comparisons of timings + * can be done by the TimeMonitor. + *
    + */ + + class Time + { + + public: + /** \brief Construct with a descriptive name */ + Time(const std::string& name, bool start = false); + + /** \brief Returns current wall-clock time in seconds.*/ + static double wallTime(); + + /** \brief Starts the timer */ + void start(bool reset = false); + + /** \brief Stops the timer */ + double stop(); + + /** \brief Returns the total time accumulated by this timer. This should be called + * only when the clock is stopped. */ + double totalElapsedTime(bool readCurrentTime = false) const; + + /** \brief Resets the cummulative time and number of times this timer + * has been called. Does not affect any other state. */ + void reset() {totalTime_ = 0; numCalls_ = 0;} + + /** \brief Indicates if this timer is currently running, i.e., if it has been started but + * not yet stopped. + * + * It is necessary to know if a timer is running to avoid incorrectly starting or + * stopping in reentrant code. */ + bool isRunning() const {return isRunning_;} + + /** \brief Return the name of this timer */ + const std::string& name() const {return name_;} + + /** \brief Increment the number of times this timer has been called */ + void incrementNumCalls() {numCalls_++;} + + /** \brief Return the number of times this timer has been called */ + int numCalls() const {return numCalls_;} + + private: + double startTime_; + + double totalTime_; + + bool isRunning_; + + std::string name_; + + int numCalls_; + }; + +} // namespace Teuchos + +#endif // TEUCHOS_TIME_HPP_ diff --git a/fastlib/trilinos/include/Teuchos_TimeMonitor.hpp b/fastlib/trilinos/include/Teuchos_TimeMonitor.hpp new file mode 100644 index 0000000000..31541f3b59 --- /dev/null +++ b/fastlib/trilinos/include/Teuchos_TimeMonitor.hpp @@ -0,0 +1,169 @@ +// @HEADER +// *********************************************************************** +// +// Teuchos: Common Tools Package +// Copyright (2004) Sandia Corporation +// +// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive +// license for use of this work by or on behalf of the U.S. Government. +// +// This library is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of the +// License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// Questions? Contact Michael A. Heroux (maherou@sandia.gov) +// +// *********************************************************************** +// @HEADER + +#ifndef TEUCHOS_TIMEMONITOR_HPP +#define TEUCHOS_TIMEMONITOR_HPP + + +/*! \file Teuchos_TimeMonitor.hpp + * + * \brief Timer class that starts when constructed and stops when the + * destructor is called + */ + +/** \example TimeMonitor/cxx_main.cpp + * + * This is an example of how to use the Teuchos::TimeMonitor class. + */ + + +#include "Teuchos_ConfigDefs.hpp" +#include "Teuchos_PerformanceMonitorBase.hpp" +#include "Teuchos_Time.hpp" + + +/** \brief Defines a static non-member function that returns a time monitor. + */ +#define TEUCHOS_TIMER(funcName, strName) \ + static Teuchos::Time& funcName() \ + {static Teuchos::RCP