<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
//...
//  Checks the quality assurance.
//  By comparing with reference data
//  Skeleton for T0
//---------------------------------------------
//checkig without reference data:
//for RAW QA all histograms should have approximatly the same
//number of entries as RefPoint
//for Rec Points checks
//  - amplitude measured by 2 methos
//  - online and offline T0 measurements
// for ESD quality of reconstruction ( and measurements):
// RMS of vertex and T0 less than 75ps
//
// Alla.Maevskaya@cern.ch
//...

// --- ROOT system ---
#include <Riostream.h>
#include <TClass.h>
#include <TH1F.h>
#include <TF1.h>
#include <TFitResultPtr.h>
#include <TH2.h>
#include <TIterator.h>
#include <TKey.h>
#include <TFile.h>
#include <TMath.h>
#include <TString.h>
#include <TPaveText.h>

// --- Standard library ---

// --- AliRoot header files ---
#include "AliLog.h"
#include "AliQAv1.h"
#include "AliQAChecker.h"
#include "AliCDBEntry.h"
#include "AliQAManager.h"
#include "AliT0QAChecker.h"

ClassImp(AliT0QAChecker)
//____________________________________________________________________________
AliT0QAChecker::AliT0QAChecker() :
AliQACheckerBase("T0","T0 Quality Assurance Checker")

{
  // Standard constructor

}

//____________________________________________________________________________
AliT0QAChecker::AliT0QAChecker(const AliT0QAChecker& qac):
  AliQACheckerBase(qac.GetName(), qac.GetTitle())
{
  // copy constructor
  AliError("Copy should not be used with this class\n");
}
//____________________________________________________________________________
AliT0QAChecker& AliT0QAChecker::operator=(const AliT0QAChecker& qac){
  // assignment operator
  this->~AliT0QAChecker();
  new(this)AliT0QAChecker(qac);
  return *this;
}

//____________________________________________________________________________
AliT0QAChecker::~AliT0QAChecker(){
  // destructor

}

//__________________________________________________________________
void AliT0QAChecker::Check(Double_t *  test, AliQAv1::ALITASK_t index, TObjArray ** list, const AliDetectorRecoParam * /*recoParam*/)
{

  // Super-basic check on the QA histograms on the input list:
  // look whether they are empty!

 char * detOCDBDir = Form("T0/%s/%s", AliQAv1::GetRefOCDBDirName(), AliQAv1::GetRefDataDirName()) ;

  AliCDBEntry *QARefRec = AliQAManager::QAManager()->Get(detOCDBDir);
  //  QARefRec->Dump();
  if( !QARefRec){
    AliInfo("QA reference data NOT retrieved for Reconstruction check. No T0 reference distribution");
  }

  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
    test[specie]    = 10.0 ;

  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
    //  TString dataType = AliQAv1::GetAliTaskName(index);
    if (!(AliQAv1::Instance()->IsEventSpecieSet(specie) && list[specie]) || list[specie]->GetEntries() == 0) {
      test[specie] = 1. ; // nothing to check
      continue;
    }
    if (index == AliQAv1::kRAW && AliRecoParam::ConvertIndex(specie) == AliRecoParam::kCalib)
      //      if (index == AliQAv1::kRAW )
      {
	test[specie] = CheckRaw(list[specie]);
      }
    if (index == AliQAv1::kESD && AliRecoParam::Convert(specie) != AliRecoParam::kCalib)
      test[specie] = CheckESD(list[specie]);
    //
  }
}

//--------------------------------------------------------------------------
Double_t AliT0QAChecker::CheckRaw(TObjArray *listrec) const
{
   Float_t checkr = 0;

  TString hname[10];
   TH1*hdata;
   const char *cname;
   TH1 *fhRawEff[10];
   Int_t nh=0;

   //   Int_t nnn[4] = { 420, 458, 459, 460};
   Int_t nnn[4] = { 170, 208, 209, 210};
   for (Int_t ir=0; ir<4; ir++)
     {
	 hdata = (TH1*) listrec->UncheckedAt(nnn[ir]);
	 if(hdata) {
	   cname = hdata->GetName();
	   hname[ir] = cname;
	   fhRawEff[nh] = hdata;
	   nh++;
	 }
    }

   TLine *linelowyellow = new TLine(0, 0.7, 24, 0.7);
   linelowyellow->SetLineColor(5);
   linelowyellow->SetLineStyle(3);
   linelowyellow->SetLineWidth(4);
   TLine *linelowred = new TLine(0, 0.2, 24, 0.2);
   linelowred->SetLineColor(2);
   linelowred->SetLineStyle(3);
   linelowred->SetLineWidth(4);

   Float_t thryell = 0.7;
   //   TPaveText* text = new TPaveText(0.30,0.50,0.99,0.99,"NDC");
   Float_t thrred = 0.2;
   Float_t chcont =0;
    for (Int_t ih= 0; ih<4; ih++)
     {
       fhRawEff[ih]->SetLineWidth(2);
       fhRawEff[ih]->SetMaximum(2.);
       fhRawEff[ih]->SetMinimum(0.);
       fhRawEff[ih]->GetListOfFunctions()->Add(linelowyellow);
       fhRawEff[ih]->GetListOfFunctions()->Add(linelowred);

       Int_t nbins= fhRawEff[ih]->GetNbinsX();
       Bool_t yell = kFALSE;
       Bool_t red = kFALSE;
       for (Int_t in=1; in<nbins-1; in++)
	 {
	   if(ih==0 && in==5) continue;
	   chcont=fhRawEff[ih]->GetBinContent(in);
	   if (chcont < thryell  ) yell = kTRUE;
	   if (chcont < thrred  ) red = kTRUE;
	 }

       if (! yell && !red) {
	 AliDebug(AliQAv1::GetQADebugLevel(), Form(" efficiency in all channes %s  is good", fhRawEff[ih]->GetName() ));
	 checkr=1.;
	 //	 text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
	 //	 text->AddText(Form(" No problems "));
	 //	 text->SetFillColor(3);
       }

       if(red ) {
	 checkr = 0.;
	 AliDebug(AliQAv1::GetQADebugLevel(), Form(" efficiency in all channes %s  is not so good", fhRawEff[ih]->GetName() ));
	 //	 text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
	 //	 text->AddText(Form("Very serious problem, call expert "));
	 //	 text->SetFillColor(2);
       }

       if ( yell && !red) {
	 AliDebug(AliQAv1::GetQADebugLevel(), Form(" efficiency in all channes %s  is not so good", fhRawEff[ih]->GetName() ));
	 checkr=0.75;
	 //	 text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
	 //	 text->AddText(Form("Some problems "));
	 //	 text->SetFillColor(5);
      }
       // fhRawEff[ih]->GetListOfFunctions()->Add(text);

     }
  return checkr;

}

//--------------------------------------------------------------------------
Double_t AliT0QAChecker::CheckESD(TObjArray *listrec ) const
{
  Float_t checkr = 0;
  TH1 *fhESD;

  fhESD  = (TH1*) listrec->UncheckedAt(2);
  if(fhESD){
    AliDebug(AliQAv1::GetQADebugLevel(), Form("count %s ", fhESD->GetName()) );
     TF1 *f1 = new TF1("f1","gaus",-1,1);
    fhESD->Fit("f1","R","Q", -1,1);
    Double_t par[3];
    f1->GetParameters(&par[0]);

    TPaveText* text = new TPaveText(0.30,0.50,0.99,0.99,"NDC");

    text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));

    AliDebug(AliQAv1::GetQADebugLevel(), Form("numentries %d mean %f  #sigma %f", (int)fhESD->GetEntries(),par[1], par[2]));

    if (par[2] > 0.07 && par[2] < 1.) {
      checkr=0.5;
       text->AddText(Form("not good resolution :\n %f ns\n", par[2] ));
       text->SetFillColor(5);
       printf("T0 detector resolution is not good enouph: %f ns\n",par[2] );
    }
    if(TMath::Abs(par[1])>0.05) {
      checkr = 0.5;
      text->AddText(Form(" Check clock shift on %f ns", par[1]));
      text->SetFillColor(5);
    }
    if (par[2] >  1. || TMath::Abs(par[1])>0.1) {
      checkr = 0.25;
      text->AddText(Form(" Bad resolution:\n mean %f ns sigma %f ns", par[1], par[2]));
      text->SetFillColor(2);

      fhESD->GetListOfFunctions()->Add(text);
       AliDebug(AliQAv1::GetQADebugLevel(),
		Form("Please, check calibration: shift= %f resolution %f test=%f\n",
		     par[1], par[2], checkr) ) ;
    }
  }
  else
    {
      AliDebug(AliQAv1::GetQADebugLevel(),
	       Form("No ESD QA histogram found, nothing to check"));
	checkr=0;
    }

  return checkr;
}
<commit_msg> crash of T0 QA Agent fixed<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/
//...
//  Checks the quality assurance.
//  By comparing with reference data
//  Skeleton for T0
//---------------------------------------------
//checkig without reference data:
//for RAW QA all histograms should have approximatly the same
//number of entries as RefPoint
//for Rec Points checks
//  - amplitude measured by 2 methos
//  - online and offline T0 measurements
// for ESD quality of reconstruction ( and measurements):
// RMS of vertex and T0 less than 75ps
//
// Alla.Maevskaya@cern.ch
//...

// --- ROOT system ---
#include <Riostream.h>
#include <TClass.h>
#include <TH1F.h>
#include <TF1.h>
#include <TFitResultPtr.h>
#include <TH2.h>
#include <TIterator.h>
#include <TKey.h>
#include <TFile.h>
#include <TMath.h>
#include <TString.h>
#include <TPaveText.h>

// --- Standard library ---

// --- AliRoot header files ---
#include "AliLog.h"
#include "AliQAv1.h"
#include "AliQAChecker.h"
#include "AliCDBEntry.h"
#include "AliQAManager.h"
#include "AliT0QAChecker.h"

ClassImp(AliT0QAChecker)
//____________________________________________________________________________
AliT0QAChecker::AliT0QAChecker() :
AliQACheckerBase("T0","T0 Quality Assurance Checker")

{
  // Standard constructor

}

//____________________________________________________________________________
AliT0QAChecker::AliT0QAChecker(const AliT0QAChecker& qac):
  AliQACheckerBase(qac.GetName(), qac.GetTitle())
{
  // copy constructor
  AliError("Copy should not be used with this class\n");
}
//____________________________________________________________________________
AliT0QAChecker& AliT0QAChecker::operator=(const AliT0QAChecker& qac){
  // assignment operator
  this->~AliT0QAChecker();
  new(this)AliT0QAChecker(qac);
  return *this;
}

//____________________________________________________________________________
AliT0QAChecker::~AliT0QAChecker(){
  // destructor

}

//__________________________________________________________________
void AliT0QAChecker::Check(Double_t *  test, AliQAv1::ALITASK_t index, TObjArray ** list, const AliDetectorRecoParam * /*recoParam*/)
{

  // Super-basic check on the QA histograms on the input list:
  // look whether they are empty!

 char * detOCDBDir = Form("T0/%s/%s", AliQAv1::GetRefOCDBDirName(), AliQAv1::GetRefDataDirName()) ;

  AliCDBEntry *QARefRec = AliQAManager::QAManager()->Get(detOCDBDir);
  //  QARefRec->Dump();
  if( !QARefRec){
    AliInfo("QA reference data NOT retrieved for Reconstruction check. No T0 reference distribution");
  }

  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
    test[specie]    = 10.0 ;

  for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
    //  TString dataType = AliQAv1::GetAliTaskName(index);
    if (!(AliQAv1::Instance()->IsEventSpecieSet(specie) && list[specie]) || list[specie]->GetEntries() == 0) {
      test[specie] = 1. ; // nothing to check
      continue;
    }
    if (index == AliQAv1::kRAW && AliRecoParam::ConvertIndex(specie) == AliRecoParam::kCalib)
      //      if (index == AliQAv1::kRAW )
      {
	test[specie] = CheckRaw(list[specie]);
      }
    if (index == AliQAv1::kESD && AliRecoParam::Convert(specie) != AliRecoParam::kCalib)
      test[specie] = CheckESD(list[specie]);
    //
  }
}

//--------------------------------------------------------------------------
Double_t AliT0QAChecker::CheckRaw(TObjArray *listrec) const
{
   Float_t checkr = 0;

  TString hname[10];
   TH1*hdata;
   const char *cname;
   TH1 *fhRawEff[10];
   Int_t nh=0;

   //   Int_t nnn[4] = { 420, 458, 459, 460};
   Int_t nnn[4] = { 169, 207, 208, 209};
   for (Int_t ir=0; ir<4; ir++)
     {
	 hdata = (TH1*) listrec->UncheckedAt(nnn[ir]);
	 if(hdata) {
	   cname = hdata->GetName();
	   hname[ir] = cname;
	   fhRawEff[nh] = hdata;
	   nh++;
	 }
    }

   TLine *linelowyellow = new TLine(0, 0.7, 24, 0.7);
   linelowyellow->SetLineColor(5);
   linelowyellow->SetLineStyle(3);
   linelowyellow->SetLineWidth(4);
   TLine *linelowred = new TLine(0, 0.2, 24, 0.2);
   linelowred->SetLineColor(2);
   linelowred->SetLineStyle(3);
   linelowred->SetLineWidth(4);

   Float_t thryell = 0.7;
   //   TPaveText* text = new TPaveText(0.30,0.50,0.99,0.99,"NDC");
   Float_t thrred = 0.2;
   Float_t chcont =0;
    for (Int_t ih= 0; ih<4; ih++)
     {
       fhRawEff[ih]->SetLineWidth(2);
       fhRawEff[ih]->SetMaximum(2.);
       fhRawEff[ih]->SetMinimum(0.);
       fhRawEff[ih]->GetListOfFunctions()->Add(linelowyellow);
       fhRawEff[ih]->GetListOfFunctions()->Add(linelowred);

       Int_t nbins= fhRawEff[ih]->GetNbinsX();
       Bool_t yell = kFALSE;
       Bool_t red = kFALSE;
       for (Int_t in=1; in<nbins-1; in++)
	 {
	   if(ih==0 && in==5) continue;
	   chcont=fhRawEff[ih]->GetBinContent(in);
	   if (chcont < thryell  ) yell = kTRUE;
	   if (chcont < thrred  ) red = kTRUE;
	 }

       if (! yell && !red) {
	 AliDebug(AliQAv1::GetQADebugLevel(), Form(" efficiency in all channes %s  is good", fhRawEff[ih]->GetName() ));
	 checkr=1.;
	 //	 text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
	 //	 text->AddText(Form(" No problems "));
	 //	 text->SetFillColor(3);
       }

       if(red ) {
	 checkr = 0.;
	 AliDebug(AliQAv1::GetQADebugLevel(), Form(" efficiency in all channes %s  is not so good", fhRawEff[ih]->GetName() ));
	 //	 text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
	 //	 text->AddText(Form("Very serious problem, call expert "));
	 //	 text->SetFillColor(2);
       }

       if ( yell && !red) {
	 AliDebug(AliQAv1::GetQADebugLevel(), Form(" efficiency in all channes %s  is not so good", fhRawEff[ih]->GetName() ));
	 checkr=0.75;
	 //	 text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));
	 //	 text->AddText(Form("Some problems "));
	 //	 text->SetFillColor(5);
      }
       // fhRawEff[ih]->GetListOfFunctions()->Add(text);

     }
  return checkr;

}

//--------------------------------------------------------------------------
Double_t AliT0QAChecker::CheckESD(TObjArray *listrec ) const
{
  Float_t checkr = 0;
  TH1 *fhESD;

  fhESD  = (TH1*) listrec->UncheckedAt(2);
  if(fhESD){
    AliDebug(AliQAv1::GetQADebugLevel(), Form("count %s ", fhESD->GetName()) );
     TF1 *f1 = new TF1("f1","gaus",-1,1);
    fhESD->Fit("f1","R","Q", -1,1);
    Double_t par[3];
    f1->GetParameters(&par[0]);

    TPaveText* text = new TPaveText(0.30,0.50,0.99,0.99,"NDC");

    text->AddText(Form("T0 RUN %d ",AliCDBManager::Instance()->GetRun()));

    AliDebug(AliQAv1::GetQADebugLevel(), Form("numentries %d mean %f  #sigma %f", (int)fhESD->GetEntries(),par[1], par[2]));

    if (par[2] > 0.07 && par[2] < 1.) {
      checkr=0.5;
       text->AddText(Form("not good resolution :\n %f ns\n", par[2] ));
       text->SetFillColor(5);
       printf("T0 detector resolution is not good enouph: %f ns\n",par[2] );
    }
    if(TMath::Abs(par[1])>0.05) {
      checkr = 0.5;
      text->AddText(Form(" Check clock shift on %f ns", par[1]));
      text->SetFillColor(5);
    }
    if (par[2] >  1. || TMath::Abs(par[1])>0.1) {
      checkr = 0.25;
      text->AddText(Form(" Bad resolution:\n mean %f ns sigma %f ns", par[1], par[2]));
      text->SetFillColor(2);

      fhESD->GetListOfFunctions()->Add(text);
       AliDebug(AliQAv1::GetQADebugLevel(),
		Form("Please, check calibration: shift= %f resolution %f test=%f\n",
		     par[1], par[2], checkr) ) ;
    }
  }
  else
    {
      AliDebug(AliQAv1::GetQADebugLevel(),
	       Form("No ESD QA histogram found, nothing to check"));
	checkr=0;
    }

  return checkr;
}
<|endoftext|>


<commit_before>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/
/*!
 * \file   tstMapInterface.cpp
 * \author Stuart Slattery
 * \brief  DTK view unit tests.
 */
//---------------------------------------------------------------------------//

#include <DTK_C_API.h>
#include <DTK_ParallelTraits.hpp>

#include <Teuchos_DefaultComm.hpp>
#include <Teuchos_DefaultMpiComm.hpp>
#include <Teuchos_UnitTestHarness.hpp>

#include <Kokkos_Core.hpp>

#include <memory>

//---------------------------------------------------------------------------//
// User implementation
template <class Space>
struct TestUserData
{
    Kokkos::View<double * [3], Space> coords;
    Kokkos::View<double *, Space> field;

    TestUserData( const int size )
        : coords( "coords", size )
        , field( "field", size )
    {
    }
};

template <class Space>
void nodeListSize( void *user_data, unsigned *space_dim,
                   size_t *local_num_nodes )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    *space_dim = data->coords.extent( 1 );
    *local_num_nodes = data->coords.extent( 0 );
}

template <class Space>
void nodeListData( void *user_data, Coordinate *coords )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    int num_node = data->coords.extent( 0 );
    for ( unsigned n = 0; n < data->coords.extent( 0 ); ++n )
        for ( unsigned d = 0; d < data->coords.extent( 1 ); ++d )
            coords[num_node * d + n] = data->coords( n, d );
}

template <class Space>
void fieldSize( void *user_data, const char *field_name,
                unsigned *field_dimension, size_t *local_num_dofs )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    *field_dimension = 1;
    *local_num_dofs = data->field.extent( 0 );
}

template <class Space>
void pullField( void *user_data, const char *, double *field_dofs )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    for ( unsigned i = 0; i < data->field.extent( 0 ); ++i )
        field_dofs[i] = data->field( i );
}
template <class Space>
void pushField( void *user_data, const char *, const double *field_dofs )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    for ( unsigned i = 0; i < data->field.extent( 0 ); ++i )
        data->field( i ) = field_dofs[i];
}

//---------------------------------------------------------------------------//
// Test execution space enumeration selector.
template <class Space>
struct SpaceSelector;

#if defined( KOKKOS_ENABLE_SERIAL )
template <>
struct SpaceSelector<DataTransferKit::Serial>
{
    static constexpr DTK_ExecutionSpace value() { return DTK_SERIAL; }
};
#endif

#if defined( KOKKOS_ENABLE_OPENMP )
template <>
struct SpaceSelector<DataTransferKit::OpenMP>
{
    static constexpr DTK_ExecutionSpace value() { return DTK_OPENMP; }
};
#endif

#if defined( KOKKOS_ENABLE_SERIAL ) || defined( KOKKOS_ENABLE_OPENMP )
template <>
struct SpaceSelector<DataTransferKit::HostSpace>
{
    static constexpr DTK_MemorySpace value() { return DTK_HOST_SPACE; }
};
#endif

#if defined( KOKKOS_ENABLE_CUDA )
template <>
struct SpaceSelector<DataTransferKit::Cuda>
{
    static constexpr DTK_ExecutionSpace value() { return DTK_CUDA; }
};

template <>
struct SpaceSelector<DataTransferKit::CudaUVMSpace>
{
    static constexpr DTK_MemorySpace value() { return DTK_CUDAUVM_SPACE; }
};
#endif

//---------------------------------------------------------------------------//
// Run the test.
template <class MapSpace, class SourceSpace, class TargetSpace>
void test( bool &success, Teuchos::FancyOStream &out )
{
    // Initialize DTK. The test harness initializes kokkos already.
    DTK_initialize();
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Check error handling on a bad map.
    DTK_MapHandle bad_handle = nullptr;
    DTK_applyMap( bad_handle, "bad", "bad" );
    TEST_EQUALITY( errno, DTK_INVALID_HANDLE );
    DTK_destroyMap( bad_handle );
    TEST_EQUALITY( errno, DTK_INVALID_HANDLE );

    // Get the communicator
    auto teuchos_comm = Teuchos::DefaultComm<int>::getComm();

    // Create a source and target data set.
    int num_point = 1000;
    auto src_data = std::make_shared<TestUserData<SourceSpace>>( num_point );
    auto tgt_data = std::make_shared<TestUserData<TargetSpace>>( num_point );

    // Assign source and target points and some field data. Make the points
    // the same for now to test the nearest neighbor operator. Invert the rank
    // though so at least they live on different processors.
    int comm_rank = teuchos_comm->getRank();
    int inverse_rank = teuchos_comm->getSize() - comm_rank - 1;
    for ( int p = 0; p < num_point; ++p )
    {
        for ( int d = 0; d < 3; ++d )
        {

            src_data->coords( p, d ) = 1.0 * p + comm_rank * num_point;
            tgt_data->coords( p, d ) = 1.0 * p + inverse_rank * num_point;
        }
        src_data->field( p ) = 1.0 * p + comm_rank * num_point;
        tgt_data->field( p ) = 0.0;
    }

    // Create the source user application instance.
    auto src_handle =
        DTK_createUserApplication( SpaceSelector<SourceSpace>::value() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_NODE_LIST_SIZE_FUNCTION,
                         ( void ( * )() ) & nodeListSize<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_NODE_LIST_DATA_FUNCTION,
                         ( void ( * )() ) & nodeListData<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_FIELD_SIZE_FUNCTION,
                         ( void ( * )() ) & fieldSize<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_PULL_FIELD_DATA_FUNCTION,
                         ( void ( * )() ) & pullField<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Create the target user application instance.
    auto tgt_handle =
        DTK_createUserApplication( SpaceSelector<TargetSpace>::value() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_NODE_LIST_SIZE_FUNCTION,
                         ( void ( * )() ) & nodeListSize<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_NODE_LIST_DATA_FUNCTION,
                         ( void ( * )() ) & nodeListData<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_FIELD_SIZE_FUNCTION,
                         ( void ( * )() ) & fieldSize<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_PUSH_FIELD_DATA_FUNCTION,
                         ( void ( * )() ) & pushField<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Create a map.
    const std::string options = "{ \"Map Type\": \"Nearest Neighbor\" }";
    auto comm = Teuchos::getRawMpiComm( *teuchos_comm );
    auto map_handle = DTK_createMap( SpaceSelector<MapSpace>::value(), comm,
                                     src_handle, tgt_handle, options.c_str() );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Apply the map.
    DTK_applyMap( map_handle, "dummy", "dummy" );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Check the results. The points are the same and the current
    // implementation of the map C interface uses nearest neighbor so we
    // should get the same result.
    for ( int p = 0; p < num_point; ++p )
    {
        TEST_EQUALITY( tgt_data->field( p ),
                       1.0 * p + inverse_rank * num_point );
    }

    // Cleanup.
    DTK_destroyMap( map_handle );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_destroyUserApplication( src_handle );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_destroyUserApplication( tgt_handle );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_finalize();
    TEST_EQUALITY( errno, DTK_SUCCESS );
}

//---------------------------------------------------------------------------//
// TESTS
//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_SERIAL )
TEUCHOS_UNIT_TEST( MapInterface, Serial )
{
    test<DataTransferKit::Serial, DataTransferKit::HostSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_OPENMP )
TEUCHOS_UNIT_TEST( MapInterface, OpenMP )
{
    test<DataTransferKit::OpenMP, DataTransferKit::HostSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, Cuda )
{
    test<DataTransferKit::Cuda, DataTransferKit::CudaUVMSpace,
         DataTransferKit::CudaUVMSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_SERIAL ) && defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, SerialAndCuda )
{
    test<DataTransferKit::Serial, DataTransferKit::CudaUVMSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::Serial, DataTransferKit::HostSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::Serial, DataTransferKit::CudaUVMSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_OPENMP ) && defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, OpenmpAndCuda )
{
    test<DataTransferKit::OpenMP, DataTransferKit::CudaUVMSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::OpenMP, DataTransferKit::HostSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::OpenMP, DataTransferKit::CudaUVMSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if ( defined( KOKKOS_ENABLE_SERIAL ) || defined( KOKKOS_ENABLE_OPENMP ) ) &&  \
    defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, HostAndCuda )
{
    test<DataTransferKit::Cuda, DataTransferKit::HostSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::Cuda, DataTransferKit::CudaUVMSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
// end tstMapInterface.cpp
//---------------------------------------------------------------------------//
<commit_msg>Use a string literal instead of escaping double quotes in options argument<commit_after>/****************************************************************************
 * Copyright (c) 2012-2018 by the DataTransferKit authors                   *
 * All rights reserved.                                                     *
 *                                                                          *
 * This file is part of the DataTransferKit library. DataTransferKit is     *
 * distributed under a BSD 3-clause license. For the licensing terms see    *
 * the LICENSE file in the top-level directory.                             *
 *                                                                          *
 * SPDX-License-Identifier: BSD-3-Clause                                    *
 ****************************************************************************/
/*!
 * \file   tstMapInterface.cpp
 * \author Stuart Slattery
 * \brief  DTK view unit tests.
 */
//---------------------------------------------------------------------------//

#include <DTK_C_API.h>
#include <DTK_ParallelTraits.hpp>

#include <Teuchos_DefaultComm.hpp>
#include <Teuchos_DefaultMpiComm.hpp>
#include <Teuchos_UnitTestHarness.hpp>

#include <Kokkos_Core.hpp>

#include <memory>

//---------------------------------------------------------------------------//
// User implementation
template <class Space>
struct TestUserData
{
    Kokkos::View<double * [3], Space> coords;
    Kokkos::View<double *, Space> field;

    TestUserData( const int size )
        : coords( "coords", size )
        , field( "field", size )
    {
    }
};

template <class Space>
void nodeListSize( void *user_data, unsigned *space_dim,
                   size_t *local_num_nodes )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    *space_dim = data->coords.extent( 1 );
    *local_num_nodes = data->coords.extent( 0 );
}

template <class Space>
void nodeListData( void *user_data, Coordinate *coords )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    int num_node = data->coords.extent( 0 );
    for ( unsigned n = 0; n < data->coords.extent( 0 ); ++n )
        for ( unsigned d = 0; d < data->coords.extent( 1 ); ++d )
            coords[num_node * d + n] = data->coords( n, d );
}

template <class Space>
void fieldSize( void *user_data, const char *field_name,
                unsigned *field_dimension, size_t *local_num_dofs )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    *field_dimension = 1;
    *local_num_dofs = data->field.extent( 0 );
}

template <class Space>
void pullField( void *user_data, const char *, double *field_dofs )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    for ( unsigned i = 0; i < data->field.extent( 0 ); ++i )
        field_dofs[i] = data->field( i );
}
template <class Space>
void pushField( void *user_data, const char *, const double *field_dofs )
{
    TestUserData<Space> *data = static_cast<TestUserData<Space> *>( user_data );
    for ( unsigned i = 0; i < data->field.extent( 0 ); ++i )
        data->field( i ) = field_dofs[i];
}

//---------------------------------------------------------------------------//
// Test execution space enumeration selector.
template <class Space>
struct SpaceSelector;

#if defined( KOKKOS_ENABLE_SERIAL )
template <>
struct SpaceSelector<DataTransferKit::Serial>
{
    static constexpr DTK_ExecutionSpace value() { return DTK_SERIAL; }
};
#endif

#if defined( KOKKOS_ENABLE_OPENMP )
template <>
struct SpaceSelector<DataTransferKit::OpenMP>
{
    static constexpr DTK_ExecutionSpace value() { return DTK_OPENMP; }
};
#endif

#if defined( KOKKOS_ENABLE_SERIAL ) || defined( KOKKOS_ENABLE_OPENMP )
template <>
struct SpaceSelector<DataTransferKit::HostSpace>
{
    static constexpr DTK_MemorySpace value() { return DTK_HOST_SPACE; }
};
#endif

#if defined( KOKKOS_ENABLE_CUDA )
template <>
struct SpaceSelector<DataTransferKit::Cuda>
{
    static constexpr DTK_ExecutionSpace value() { return DTK_CUDA; }
};

template <>
struct SpaceSelector<DataTransferKit::CudaUVMSpace>
{
    static constexpr DTK_MemorySpace value() { return DTK_CUDAUVM_SPACE; }
};
#endif

//---------------------------------------------------------------------------//
// Run the test.
template <class MapSpace, class SourceSpace, class TargetSpace>
void test( bool &success, Teuchos::FancyOStream &out )
{
    // Initialize DTK. The test harness initializes kokkos already.
    DTK_initialize();
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Check error handling on a bad map.
    DTK_MapHandle bad_handle = nullptr;
    DTK_applyMap( bad_handle, "bad", "bad" );
    TEST_EQUALITY( errno, DTK_INVALID_HANDLE );
    DTK_destroyMap( bad_handle );
    TEST_EQUALITY( errno, DTK_INVALID_HANDLE );

    // Get the communicator
    auto teuchos_comm = Teuchos::DefaultComm<int>::getComm();

    // Create a source and target data set.
    int num_point = 1000;
    auto src_data = std::make_shared<TestUserData<SourceSpace>>( num_point );
    auto tgt_data = std::make_shared<TestUserData<TargetSpace>>( num_point );

    // Assign source and target points and some field data. Make the points
    // the same for now to test the nearest neighbor operator. Invert the rank
    // though so at least they live on different processors.
    int comm_rank = teuchos_comm->getRank();
    int inverse_rank = teuchos_comm->getSize() - comm_rank - 1;
    for ( int p = 0; p < num_point; ++p )
    {
        for ( int d = 0; d < 3; ++d )
        {

            src_data->coords( p, d ) = 1.0 * p + comm_rank * num_point;
            tgt_data->coords( p, d ) = 1.0 * p + inverse_rank * num_point;
        }
        src_data->field( p ) = 1.0 * p + comm_rank * num_point;
        tgt_data->field( p ) = 0.0;
    }

    // Create the source user application instance.
    auto src_handle =
        DTK_createUserApplication( SpaceSelector<SourceSpace>::value() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_NODE_LIST_SIZE_FUNCTION,
                         ( void ( * )() ) & nodeListSize<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_NODE_LIST_DATA_FUNCTION,
                         ( void ( * )() ) & nodeListData<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_FIELD_SIZE_FUNCTION,
                         ( void ( * )() ) & fieldSize<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( src_handle, DTK_PULL_FIELD_DATA_FUNCTION,
                         ( void ( * )() ) & pullField<SourceSpace>,
                         src_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Create the target user application instance.
    auto tgt_handle =
        DTK_createUserApplication( SpaceSelector<TargetSpace>::value() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_NODE_LIST_SIZE_FUNCTION,
                         ( void ( * )() ) & nodeListSize<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_NODE_LIST_DATA_FUNCTION,
                         ( void ( * )() ) & nodeListData<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_FIELD_SIZE_FUNCTION,
                         ( void ( * )() ) & fieldSize<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_setUserFunction( tgt_handle, DTK_PUSH_FIELD_DATA_FUNCTION,
                         ( void ( * )() ) & pushField<TargetSpace>,
                         tgt_data.get() );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Create a map.
    std::string const options = R"({ "Map Type": "Nearest Neighbor" })";
    auto comm = Teuchos::getRawMpiComm( *teuchos_comm );
    auto map_handle = DTK_createMap( SpaceSelector<MapSpace>::value(), comm,
                                     src_handle, tgt_handle, options.c_str() );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Apply the map.
    DTK_applyMap( map_handle, "dummy", "dummy" );
    TEST_EQUALITY( errno, DTK_SUCCESS );

    // Check the results. The points are the same and the current
    // implementation of the map C interface uses nearest neighbor so we
    // should get the same result.
    for ( int p = 0; p < num_point; ++p )
    {
        TEST_EQUALITY( tgt_data->field( p ),
                       1.0 * p + inverse_rank * num_point );
    }

    // Cleanup.
    DTK_destroyMap( map_handle );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_destroyUserApplication( src_handle );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_destroyUserApplication( tgt_handle );
    TEST_EQUALITY( errno, DTK_SUCCESS );
    DTK_finalize();
    TEST_EQUALITY( errno, DTK_SUCCESS );
}

//---------------------------------------------------------------------------//
// TESTS
//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_SERIAL )
TEUCHOS_UNIT_TEST( MapInterface, Serial )
{
    test<DataTransferKit::Serial, DataTransferKit::HostSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_OPENMP )
TEUCHOS_UNIT_TEST( MapInterface, OpenMP )
{
    test<DataTransferKit::OpenMP, DataTransferKit::HostSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, Cuda )
{
    test<DataTransferKit::Cuda, DataTransferKit::CudaUVMSpace,
         DataTransferKit::CudaUVMSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_SERIAL ) && defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, SerialAndCuda )
{
    test<DataTransferKit::Serial, DataTransferKit::CudaUVMSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::Serial, DataTransferKit::HostSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::Serial, DataTransferKit::CudaUVMSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if defined( KOKKOS_ENABLE_OPENMP ) && defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, OpenmpAndCuda )
{
    test<DataTransferKit::OpenMP, DataTransferKit::CudaUVMSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::OpenMP, DataTransferKit::HostSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::OpenMP, DataTransferKit::CudaUVMSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
#if ( defined( KOKKOS_ENABLE_SERIAL ) || defined( KOKKOS_ENABLE_OPENMP ) ) &&  \
    defined( KOKKOS_ENABLE_CUDA )
TEUCHOS_UNIT_TEST( MapInterface, HostAndCuda )
{
    test<DataTransferKit::Cuda, DataTransferKit::HostSpace,
         DataTransferKit::CudaUVMSpace>( success, out );

    test<DataTransferKit::Cuda, DataTransferKit::CudaUVMSpace,
         DataTransferKit::HostSpace>( success, out );
}
#endif

//---------------------------------------------------------------------------//
// end tstMapInterface.cpp
//---------------------------------------------------------------------------//
<|endoftext|>


<commit_before>#ifndef DUNE_DETAILED_DISCRETIZATIONS_SPACE_INTERFACE_HH
#define DUNE_DETAILED_DISCRETIZATIONS_SPACE_INTERFACE_HH

#include <dune/common/bartonnackmanifcheck.hh>

namespace Dune {
namespace Detailed {
namespace Discretizations {

template< class Traits >
class SpaceInterface
{
public:
  typedef SpaceInterface< Traits >      ThisType;
  typedef typename Traits::derived_type derived_type;

  typedef typename Traits::GridPartType   GridPartType;
  static const int                        polOrder = Traits::polOrder;
  typedef typename GridPartType::ctype    DomainFieldType;
  static const unsigned int               dimDomain = GridPartType::dimension;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int               dimRangeRows = Traits::dimRangeRows;
  static const unsigned int               dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;
  typedef typename Traits::EntityType           EntityType;

  const GridPartType& gridPart() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().gridPart());
    return asImp().gridPart();
  }

  const BackendType& backend() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().backend());
    return asImp().backend();
  }

  bool continuous() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().continuous());
    return asImp().continuous();
  }

  const MapperType& mapper() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().mapper());
    return asImp().mapper();
  }

  BaseFunctionSetType baseFunctionSet(const EntityType& entity) const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().baseFunctionSet(entity));
    return asImp().baseFunctionSet(entity);
  }

  derived_type& asImp()
  {
    return static_cast< derived_type& >(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast< const derived_type& >(*this);
  }
}; // class SpaceInterface

} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_SPACE_INTERFACE_HH
<commit_msg>[space.interface] added methods to compute pattern<commit_after>#ifndef DUNE_DETAILED_DISCRETIZATIONS_SPACE_INTERFACE_HH
#define DUNE_DETAILED_DISCRETIZATIONS_SPACE_INTERFACE_HH

#include <dune/common/bartonnackmanifcheck.hh>
#include <dune/common/dynvector.hh>

#include <dune/stuff/la/container/pattern.hh>

namespace Dune {
namespace Detailed {
namespace Discretizations {

template< class Traits >
class SpaceInterface
{
public:
  typedef typename Traits::derived_type derived_type;

  typedef typename Traits::GridPartType   GridPartType;
  static const int                        polOrder = Traits::polOrder;
  typedef typename GridPartType::ctype    DomainFieldType;
  static const unsigned int               dimDomain = GridPartType::dimension;
  typedef typename Traits::RangeFieldType RangeFieldType;
  static const unsigned int               dimRangeRows = Traits::dimRangeRows;
  static const unsigned int               dimRangeCols = Traits::dimRangeCols;

  typedef typename Traits::BackendType          BackendType;
  typedef typename Traits::MapperType           MapperType;
  typedef typename Traits::BaseFunctionSetType  BaseFunctionSetType;
  typedef typename Traits::EntityType           EntityType;

  typedef Dune::Stuff::LA::Container::SparsityPatternDefault PatternType;

  const GridPartType& gridPart() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().gridPart());
    return asImp().gridPart();
  }

  const BackendType& backend() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().backend());
    return asImp().backend();
  }

  bool continuous() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().continuous());
    return asImp().continuous();
  }

  const MapperType& mapper() const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().mapper());
    return asImp().mapper();
  }

  BaseFunctionSetType baseFunctionSet(const EntityType& entity) const
  {
    CHECK_INTERFACE_IMPLEMENTATION(asImp().baseFunctionSet(entity));
    return asImp().baseFunctionSet(entity);
  }

  PatternType* computePattern() const
  {
    return computePattern(*this);
  }

  template< class OtherSpaceType >
  PatternType* computePattern(const OtherSpaceType& other) const
  {
    // check type of the other space
    return computePattern(gridPart(), other);
  }

  /**
   *  \brief  computes a sparsity pattern, where this space is the test space (rows/outer) and the other space is the
   *          ansatz space (cols/inner)
   */
  template< class LocalGridPartType, class O >
  PatternType* computePattern(const LocalGridPartType& localGridPart,
                              const SpaceInterface< O >& otherSpace) const
  {
    typedef typename PatternType::size_type size_type;
    PatternType* ret = new PatternType(mapper().size());
    PatternType& pattern = *ret;
    // walk the grid part
    for (typename LocalGridPartType::template Codim< 0 >::IteratorType entityIt = localGridPart.template begin< 0 >();
         entityIt != localGridPart.template end< 0 >();
         ++entityIt) {
      const typename LocalGridPartType::template Codim< 0 >::EntityType& entity = *entityIt;
      // get basefunctionsets
      const auto testBase = baseFunctionSet(entity);
      const auto ansatzBase = otherSpace.baseFunctionSet(entity);
      Dune::DynamicVector< size_t > globalRows(testBase.size(), 0);
      mapper().mapToGlobal(entity, globalRows);
      Dune::DynamicVector< size_t > globalCols(ansatzBase.size(), 0);
      otherSpace.mapper().mapToGlobal(entity, globalCols);
      for (size_t ii = 0; ii < testBase.size(); ++ii) {
        auto& columns = pattern.inner(globalRows[ii]);
        for (size_t jj = 0; jj < ansatzBase.size(); ++jj) {
          columns.insert(globalCols[jj]);
        }
      }
    } // walk the grid part
    return ret;
  } // ... computePattern(...)

  derived_type& asImp()
  {
    return static_cast< derived_type& >(*this);
  }

  const derived_type& asImp() const
  {
    return static_cast< const derived_type& >(*this);
  }
}; // class SpaceInterface

} // namespace Discretizations
} // namespace Detailed
} // namespace Dune

#endif // DUNE_DETAILED_DISCRETIZATIONS_SPACE_INTERFACE_HH
<|endoftext|>


<commit_before>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

typedef float dataType;
std::string typeName("float");

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size);

int main(int argc, char * argv[]) {
  bool reInit = false;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;
  PulsarSearch::DedispersionConf conf;
  cl::Event event;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    conf.setLocalMem(args.getSwitch("-local"));
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-local] -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

  // Allocate host memory
  std::vector< float > * shifts = PulsarSearch::getShifts(observation);
  observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + static_cast< unsigned int >(shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))));

	// Initialize OpenCL
	cl::Context clContext;
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();
  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);

	// Allocate device memory
  cl::Buffer shifts_d;
  cl::Buffer dispersedData_d;
  cl::Buffer dedispersedData_d;

  try {
  initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  } catch ( cl::Error & err ) {
    return -1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerSecond() % samples) == 0 || (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples local unroll samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread GFLOP/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
    conf.setNrSamplesPerBlock(*samples);

		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
      conf.setNrDMsPerBlock(*DMs);
			if ( conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock() > maxThreads ) {
				break;
			} else if ( (conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock()) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
        conf.setNrSamplesPerThread(samplesPerThread);
				if ( (observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 && (observation.getNrSamplesPerPaddedSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
          conf.setNrDMsPerThread(DMsPerThread);
					if ( (observation.getNrDMs() % (conf.getNrDMsPerBlock() * conf.getNrDMsPerThread())) != 0 ) {
						continue;
					} else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread()) + conf.getNrDMsPerThread() > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            conf.setUnroll(unroll);
            if ( (observation.getNrChannels() - 1) % conf.getUnroll() != 0 ) {
              continue;
            } else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread() * conf.getUnroll()) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            isa::utils::Timer timer;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(conf, typeName, observation, *shifts);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector < cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            unsigned int nrThreads = 0;
            if ( observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) == 0 ) {
              nrThreads = observation.getNrSamplesPerSecond() / conf.getNrSamplesPerThread();
            } else {
              nrThreads = observation.getNrSamplesPerPaddedSecond() / conf.getNrSamplesPerThread();
            }
            cl::NDRange global(nrThreads, observation.getNrDMs() / conf.getNrDMsPerThread());
            cl::NDRange local(conf.getNrSamplesPerBlock(), conf.getNrDMsPerBlock());

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution (";
              std::cerr << conf.print() << "): ";
              std::cerr << isa::utils::toString(err.err()) << "." << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size) {
  try {
    *shifts_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(float), 0, 0);
    *dispersedData_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, dispersedData_size * sizeof(dataType), 0, 0);
    *dedispersedData_d = cl::Buffer(clContext, CL_MEM_READ_WRITE, dedispersedData_size * sizeof(dataType), 0, 0);
    clQueue->enqueueWriteBuffer(*shifts_d, CL_FALSE, 0, shifts->size() * sizeof(float), reinterpret_cast< void * >(shifts->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<commit_msg>Fixed a bug in computing the number of samples per dispersed second.<commit_after>// Copyright 2014 Alessio Sclocco <a.sclocco@vu.nl>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include <iostream>
#include <string>
#include <vector>
#include <exception>
#include <fstream>
#include <iomanip>
#include <limits>

#include <ArgumentList.hpp>
#include <Observation.hpp>
#include <InitializeOpenCL.hpp>
#include <Kernel.hpp>
#include <Shifts.hpp>
#include <Dedispersion.hpp>
#include <utils.hpp>
#include <Timer.hpp>
#include <Stats.hpp>

typedef float dataType;
std::string typeName("float");

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size);

int main(int argc, char * argv[]) {
  bool reInit = false;
	unsigned int nrIterations = 0;
	unsigned int clPlatformID = 0;
	unsigned int clDeviceID = 0;
	unsigned int minThreads = 0;
  unsigned int maxThreads = 0;
	unsigned int maxRows = 0;
	unsigned int maxColumns = 0;
  unsigned int threadUnit = 0;
  unsigned int threadIncrement = 0;
  unsigned int maxItems = 0;
  unsigned int maxUnroll = 0;
  unsigned int maxLoopBodySize = 0;
  AstroData::Observation observation;
  PulsarSearch::DedispersionConf conf;
  cl::Event event;

	try {
    isa::utils::ArgumentList args(argc, argv);

		nrIterations = args.getSwitchArgument< unsigned int >("-iterations");
		clPlatformID = args.getSwitchArgument< unsigned int >("-opencl_platform");
		clDeviceID = args.getSwitchArgument< unsigned int >("-opencl_device");
    conf.setLocalMem(args.getSwitch("-local"));
		observation.setPadding(args.getSwitchArgument< unsigned int >("-padding"));
    threadUnit = args.getSwitchArgument< unsigned int >("-thread_unit");
		minThreads = args.getSwitchArgument< unsigned int >("-min_threads");
		maxThreads = args.getSwitchArgument< unsigned int >("-max_threads");
		maxRows = args.getSwitchArgument< unsigned int >("-max_rows");
		maxColumns = args.getSwitchArgument< unsigned int >("-max_columns");
    threadIncrement = args.getSwitchArgument< unsigned int >("-thread_increment");
		maxItems = args.getSwitchArgument< unsigned int >("-max_items");
    maxUnroll = args.getSwitchArgument< unsigned int >("-max_unroll");
    maxLoopBodySize = args.getSwitchArgument< unsigned int >("-max_loopsize");
    observation.setFrequencyRange(args.getSwitchArgument< unsigned int >("-channels"), args.getSwitchArgument< float >("-min_freq"), args.getSwitchArgument< float >("-channel_bandwidth"));
		observation.setNrSamplesPerSecond(args.getSwitchArgument< unsigned int >("-samples"));
    observation.setDMRange(args.getSwitchArgument< unsigned int >("-dms"), args.getSwitchArgument< float >("-dm_first"), args.getSwitchArgument< float >("-dm_step"));
	} catch ( isa::utils::EmptyCommandLine & err ) {
		std::cerr << argv[0] << " -iterations ... -opencl_platform ... -opencl_device ... [-local] -padding ... -thread_unit ... -min_threads ... -max_threads ... -max_items ... -max_unroll ... -max_loopsize ... -max_columns ... -max_rows ... -thread_increment ... -min_freq ... -channel_bandwidth ... -samples ... -channels ... -dms ... -dm_first ... -dm_step ..." << std::endl;
		return 1;
	} catch ( std::exception & err ) {
		std::cerr << err.what() << std::endl;
		return 1;
	}

  // Allocate host memory
  std::vector< float > * shifts = PulsarSearch::getShifts(observation);
  observation.setNrSamplesPerDispersedChannel(observation.getNrSamplesPerSecond() + static_cast< unsigned int >((shifts->at(0) * (observation.getFirstDM() + ((observation.getNrDMs() - 1) * observation.getDMStep()))) * observation.getNrSamplesPerSecond()));

	// Initialize OpenCL
	cl::Context clContext;
	std::vector< cl::Platform > * clPlatforms = new std::vector< cl::Platform >();
	std::vector< cl::Device > * clDevices = new std::vector< cl::Device >();
	std::vector< std::vector< cl::CommandQueue > > * clQueues = new std::vector< std::vector < cl::CommandQueue > >();
  isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);

	// Allocate device memory
  cl::Buffer shifts_d;
  cl::Buffer dispersedData_d;
  cl::Buffer dedispersedData_d;

  try {
  initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
  } catch ( cl::Error & err ) {
    return -1;
  }

	// Find the parameters
	std::vector< unsigned int > samplesPerBlock;
	for ( unsigned int samples = minThreads; samples <= maxColumns; samples += threadIncrement ) {
		if ( (observation.getNrSamplesPerSecond() % samples) == 0 || (observation.getNrSamplesPerPaddedSecond() % samples) == 0 ) {
			samplesPerBlock.push_back(samples);
		}
	}
	std::vector< unsigned int > DMsPerBlock;
	for ( unsigned int DMs = 1; DMs <= maxRows; DMs++ ) {
		if ( (observation.getNrDMs() % DMs) == 0 ) {
			DMsPerBlock.push_back(DMs);
		}
	}

	std::cout << std::fixed << std::endl;
	std::cout << "# nrDMs nrChannels nrSamples local unroll samplesPerBlock DMsPerBlock samplesPerThread DMsPerThread GFLOP/s time stdDeviation COV" << std::endl << std::endl;

	for ( std::vector< unsigned int >::iterator samples = samplesPerBlock.begin(); samples != samplesPerBlock.end(); ++samples ) {
    conf.setNrSamplesPerBlock(*samples);

		for ( std::vector< unsigned int >::iterator DMs = DMsPerBlock.begin(); DMs != DMsPerBlock.end(); ++DMs ) {
      conf.setNrDMsPerBlock(*DMs);
			if ( conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock() > maxThreads ) {
				break;
			} else if ( (conf.getNrSamplesPerBlock() * conf.getNrDMsPerBlock()) % threadUnit != 0 ) {
        continue;
      }

			for ( unsigned int samplesPerThread = 1; samplesPerThread <= maxItems; samplesPerThread++ ) {
        conf.setNrSamplesPerThread(samplesPerThread);
				if ( (observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 && (observation.getNrSamplesPerPaddedSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread())) != 0 ) {
					continue;
				}

				for ( unsigned int DMsPerThread = 1; DMsPerThread <= maxItems; DMsPerThread++ ) {
          conf.setNrDMsPerThread(DMsPerThread);
					if ( (observation.getNrDMs() % (conf.getNrDMsPerBlock() * conf.getNrDMsPerThread())) != 0 ) {
						continue;
					} else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread()) + conf.getNrDMsPerThread() > maxItems ) {
						break;
					}

          for ( unsigned int unroll = 1; unroll <= maxUnroll; unroll++ ) {
            conf.setUnroll(unroll);
            if ( (observation.getNrChannels() - 1) % conf.getUnroll() != 0 ) {
              continue;
            } else if ( (conf.getNrSamplesPerThread() * conf.getNrDMsPerThread() * conf.getUnroll()) > maxLoopBodySize ) {
              break;
            }
            // Generate kernel
            double gflops = isa::utils::giga(static_cast< long long unsigned int >(observation.getNrDMs()) * observation.getNrChannels() * observation.getNrSamplesPerSecond());
            isa::utils::Timer timer;
            cl::Kernel * kernel;
            std::string * code = PulsarSearch::getDedispersionOpenCL(conf, typeName, observation, *shifts);

            if ( reInit ) {
              delete clQueues;
              clQueues = new std::vector< std::vector < cl::CommandQueue > >();
              isa::OpenCL::initializeOpenCL(clPlatformID, 1, clPlatforms, &clContext, clDevices, clQueues);
              try {
                initializeDeviceMemory(clContext, &(clQueues->at(clDeviceID)[0]), shifts, &shifts_d, &dispersedData_d, observation.getNrChannels() * observation.getNrSamplesPerDispersedChannel(), &dedispersedData_d, observation.getNrDMs() * observation.getNrSamplesPerPaddedSecond());
              } catch ( cl::Error & err ) {
                return -1;
              }
              reInit = false;
            }
            try {
              kernel = isa::OpenCL::compile("dedispersion", *code, "-cl-mad-enable -Werror", clContext, clDevices->at(clDeviceID));
            } catch ( isa::OpenCL::OpenCLError & err ) {
              std::cerr << err.what() << std::endl;
              delete code;
              break;
            }
            delete code;

            unsigned int nrThreads = 0;
            if ( observation.getNrSamplesPerSecond() % (conf.getNrSamplesPerBlock() * conf.getNrSamplesPerThread()) == 0 ) {
              nrThreads = observation.getNrSamplesPerSecond() / conf.getNrSamplesPerThread();
            } else {
              nrThreads = observation.getNrSamplesPerPaddedSecond() / conf.getNrSamplesPerThread();
            }
            cl::NDRange global(nrThreads, observation.getNrDMs() / conf.getNrDMsPerThread());
            cl::NDRange local(conf.getNrSamplesPerBlock(), conf.getNrDMsPerBlock());

            kernel->setArg(0, dispersedData_d);
            kernel->setArg(1, dedispersedData_d);
            kernel->setArg(2, shifts_d);

            try {
              // Warm-up run
              clQueues->at(clDeviceID)[0].finish();
              clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
              event.wait();
              // Tuning runs
              for ( unsigned int iteration = 0; iteration < nrIterations; iteration++ ) {
                timer.start();
                clQueues->at(clDeviceID)[0].enqueueNDRangeKernel(*kernel, cl::NullRange, global, local, 0, &event);
                event.wait();
                timer.stop();
              }
            } catch ( cl::Error & err ) {
              std::cerr << "OpenCL error kernel execution (";
              std::cerr << conf.print() << "): ";
              std::cerr << isa::utils::toString(err.err()) << "." << std::endl;
              delete kernel;
              if ( err.err() == -4 || err.err() == -61 ) {
                return -1;
              }
              reInit = true;
              break;
            }
            delete kernel;

            std::cout << observation.getNrDMs() << " " << observation.getNrChannels() << " " << observation.getNrSamplesPerSecond() << " ";
            std::cout << conf.print() << " ";
            std::cout << std::setprecision(3);
            std::cout << gflops / timer.getAverageTime() << " ";
            std::cout << std::setprecision(6);
            std::cout << timer.getAverageTime() << " " << timer.getStandardDeviation() << " ";
            std::cout << timer.getCoefficientOfVariation() <<  std::endl;
          }
				}
			}
		}
	}

	std::cout << std::endl;

	return 0;
}

void initializeDeviceMemory(cl::Context & clContext, cl::CommandQueue * clQueue, std::vector< float > * shifts, cl::Buffer * shifts_d, cl::Buffer * dispersedData_d, const unsigned int dispersedData_size, cl::Buffer * dedispersedData_d, const unsigned int dedispersedData_size) {
  try {
    *shifts_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, shifts->size() * sizeof(float), 0, 0);
    *dispersedData_d = cl::Buffer(clContext, CL_MEM_READ_ONLY, dispersedData_size * sizeof(dataType), 0, 0);
    *dedispersedData_d = cl::Buffer(clContext, CL_MEM_READ_WRITE, dedispersedData_size * sizeof(dataType), 0, 0);
    clQueue->enqueueWriteBuffer(*shifts_d, CL_FALSE, 0, shifts->size() * sizeof(float), reinterpret_cast< void * >(shifts->data()));
    clQueue->finish();
  } catch ( cl::Error & err ) {
    std::cerr << "OpenCL error: " << isa::utils::toString(err.err()) << "." << std::endl;
    throw;
  }
}

<|endoftext|>


<commit_before>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkExceptionObject.h"

#include "otbStreamingStatisticsImageFilter.h"
#include "otbImageFileReader.h"
#include "otbImage.h"
#include <fstream>
#include "otbStreamingTraits.h"

int otbStreamingStatisticsImageFilter(int argc, char * argv[])
{
  try
    {
      const char * infname = argv[1];
      const char * outfname = argv[2];

      const unsigned int Dimension = 2;
      typedef double PixelType;

      typedef otb::Image<PixelType,Dimension> ImageType;
      typedef otb::ImageFileReader<ImageType> ReaderType;
      typedef otb::StreamingStatisticsImageFilter<ImageType> StreamingStatisticsImageFilterType;

      // Instantiating object
      StreamingStatisticsImageFilterType::Pointer filter = StreamingStatisticsImageFilterType::New();

      ReaderType::Pointer reader = ReaderType::New();
      reader->SetFileName(infname);

      filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
      filter->SetNumberOfStreamDivisions(200);
      filter->SetInput(reader->GetOutput());
      filter->Update();

      std::ofstream file;
      file.open(outfname);
      file<<"Statistics from image "<<infname<<":"<<std::endl;
      file<<"Minimum: "<<filter->GetMinimum()<<std::endl;
      file<<"Maximum: "<<filter->GetMaximum()<<std::endl;
      file<<"Sum: "<<filter->GetSum()<<std::endl;
      file<<"Mean: "<<filter->GetMean()<<std::endl;
      file<<"Sigma: "<<filter->GetSigma()<<std::endl;
      file<<"Variance: "<<filter->GetVariance()<<std::endl;
      file.close();
    }

  catch( itk::ExceptionObject & err )
    {
    std::cout << "Exception itk::ExceptionObject thrown !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }

  catch( ... )
    {
    std::cout << "Unknown exception thrown !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}
<commit_msg>Suppression de l'écriture du nom du fichier image dans le fichier text résultat : car chemin absolu, donc nom platform et nom du user !!!<commit_after>/*=========================================================================

  Program:   ORFEO Toolbox
  Language:  C++
  Date:      $Date$
  Version:   $Revision$

  Copyright (c) Centre National d'Etudes Spatiales. All rights reserved.
  See OTBCopyright.txt for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#include "itkExceptionObject.h"

#include "otbStreamingStatisticsImageFilter.h"
#include "otbImageFileReader.h"
#include "otbImage.h"
#include <fstream>
#include "otbStreamingTraits.h"

int otbStreamingStatisticsImageFilter(int argc, char * argv[])
{
  try
    {
      const char * infname = argv[1];
      const char * outfname = argv[2];

      const unsigned int Dimension = 2;
      typedef double PixelType;

      typedef otb::Image<PixelType,Dimension> ImageType;
      typedef otb::ImageFileReader<ImageType> ReaderType;
      typedef otb::StreamingStatisticsImageFilter<ImageType> StreamingStatisticsImageFilterType;

      // Instantiating object
      StreamingStatisticsImageFilterType::Pointer filter = StreamingStatisticsImageFilterType::New();

      ReaderType::Pointer reader = ReaderType::New();
      reader->SetFileName(infname);

      filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS);
      filter->SetNumberOfStreamDivisions(200);
      filter->SetInput(reader->GetOutput());
      filter->Update();

      std::ofstream file;
      file.open(outfname);
      file<<"Minimum: "<<filter->GetMinimum()<<std::endl;
      file<<"Maximum: "<<filter->GetMaximum()<<std::endl;
      file<<"Sum: "<<filter->GetSum()<<std::endl;
      file<<"Mean: "<<filter->GetMean()<<std::endl;
      file<<"Sigma: "<<filter->GetSigma()<<std::endl;
      file<<"Variance: "<<filter->GetVariance()<<std::endl;
      file.close();
    }

  catch( itk::ExceptionObject & err )
    {
    std::cout << "Exception itk::ExceptionObject thrown !" << std::endl;
    std::cout << err << std::endl;
    return EXIT_FAILURE;
    }

  catch( ... )
    {
    std::cout << "Unknown exception thrown !" << std::endl;
    return EXIT_FAILURE;
    }
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>
#include "DynamixelInterface.h"

void DynamixelInterface::transaction(bool aExpectStatus, uint8_t answerSize)
{
	sendPacket(mPacket);
	if(aExpectStatus)
	{
		receivePacket(mPacket, answerSize);
	}
	else
	{
		mPacket.mStatus=DYN_STATUS_OK;
	}
}

DynamixelStatus DynamixelInterface::read(uint8_t aID, uint8_t aAddress, uint8_t aSize, uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_READ, 4, aPtr, aAddress, aSize);
	transaction(aStatusReturnLevel>0 && aID!=BROADCAST_ID, aSize);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::write(uint8_t aID, uint8_t aAddress, uint8_t aSize, const uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_WRITE, aSize+3, aPtr, aAddress);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID, aSize);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::regWrite(uint8_t aID, uint8_t aAddress, uint8_t aSize, const uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_REG_WRITE, aSize+3, aPtr, aAddress);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID, aSize);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::syncWrite(uint8_t nID, const uint8_t *aID, uint8_t aAddress, uint8_t aSize, const uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(BROADCAST_ID, DYN_SYNC_WRITE, (aSize+1)*nID+4, aPtr, aAddress, aSize, nID, aID);
	transaction(false);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::ping(uint8_t aID)
{
	mPacket=DynamixelPacket(aID, DYN_PING, 2, NULL);
	transaction(true);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::action(uint8_t aID, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_ACTION, 2, NULL);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::reset(uint8_t aID, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_RESET, 2, NULL);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID);
	return mPacket.mStatus;
}

<commit_msg>size parameter only in the read<commit_after>
#include "DynamixelInterface.h"

void DynamixelInterface::transaction(bool aExpectStatus, uint8_t answerSize)
{
	sendPacket(mPacket);
	if(aExpectStatus)
	{
		receivePacket(mPacket, answerSize);
	}
	else
	{
		mPacket.mStatus=DYN_STATUS_OK;
	}
}

DynamixelStatus DynamixelInterface::read(uint8_t aID, uint8_t aAddress, uint8_t aSize, uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_READ, 4, aPtr, aAddress, aSize);
	transaction(aStatusReturnLevel>0 && aID!=BROADCAST_ID, aSize);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::write(uint8_t aID, uint8_t aAddress, uint8_t aSize, const uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_WRITE, aSize+3, aPtr, aAddress);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::regWrite(uint8_t aID, uint8_t aAddress, uint8_t aSize, const uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_REG_WRITE, aSize+3, aPtr, aAddress);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::syncWrite(uint8_t nID, const uint8_t *aID, uint8_t aAddress, uint8_t aSize, const uint8_t *aPtr, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(BROADCAST_ID, DYN_SYNC_WRITE, (aSize+1)*nID+4, aPtr, aAddress, aSize, nID, aID);
	transaction(false);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::ping(uint8_t aID)
{
	mPacket=DynamixelPacket(aID, DYN_PING, 2, NULL);
	transaction(true);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::action(uint8_t aID, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_ACTION, 2, NULL);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID);
	return mPacket.mStatus;
}

DynamixelStatus DynamixelInterface::reset(uint8_t aID, uint8_t aStatusReturnLevel)
{
	mPacket=DynamixelPacket(aID, DYN_RESET, 2, NULL);
	transaction(aStatusReturnLevel>1 && aID!=BROADCAST_ID);
	return mPacket.mStatus;
}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2012, John Haddon. All rights reserved.
//  Copyright (c) 2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/lexical_cast.hpp"

#include "Gaffer/TypedPlug.h"
#include "Gaffer/NumericPlug.h"
#include "Gaffer/CompoundDataPlug.h"

#include "GafferScene/Shader.h"

using namespace Imath;
using namespace GafferScene;
using namespace Gaffer;

IE_CORE_DEFINERUNTIMETYPED( Shader );

size_t Shader::g_firstPlugIndex = 0;

Shader::Shader( const std::string &name )
	:	DependencyNode( name )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new StringPlug( "name" ) );
	addChild( new StringPlug( "type" ) );
	addChild( new CompoundPlug( "parameters" ) );
	addChild( new BoolPlug( "enabled", Gaffer::Plug::In, true ) );
}

Shader::~Shader()
{
}

Gaffer::StringPlug *Shader::namePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const Gaffer::StringPlug *Shader::namePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

Gaffer::StringPlug *Shader::typePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

const Gaffer::StringPlug *Shader::typePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

Gaffer::CompoundPlug *Shader::parametersPlug()
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 );
}

const Gaffer::CompoundPlug *Shader::parametersPlug() const
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 );
}

Gaffer::Plug *Shader::outPlug()
{
	// not getting by index, because it is created by the
	// derived classes in loadShader().
	return getChild<Plug>( "out" );
}

const Gaffer::Plug *Shader::outPlug() const
{
	return getChild<Plug>( "out" );
}

Gaffer::BoolPlug *Shader::enabledPlug()
{
	return getChild<BoolPlug>( g_firstPlugIndex + 3 );
}

const Gaffer::BoolPlug *Shader::enabledPlug() const
{
	return getChild<BoolPlug>( g_firstPlugIndex + 3 );
}

IECore::MurmurHash Shader::stateHash() const
{
	NetworkBuilder networkBuilder( this );
	return networkBuilder.stateHash();
}

void Shader::stateHash( IECore::MurmurHash &h ) const
{
	h.append( stateHash() );
}

IECore::ConstObjectVectorPtr Shader::state() const
{
	NetworkBuilder networkBuilder( this );
	return networkBuilder.state();
}

void Shader::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	DependencyNode::affects( input, outputs );

	if( parametersPlug()->isAncestorOf( input ) || input == enabledPlug() )
	{
		const Plug *out = outPlug();
		if( out )
		{
			if( out->isInstanceOf( CompoundPlug::staticTypeId() ) )
			{
				for( RecursiveValuePlugIterator it( out ); it != it.end(); it++ )
				{
					if( !(*it)->isInstanceOf( CompoundPlug::staticTypeId() ) )
					{
						outputs.push_back( it->get() );
					}
				}
			}
			else
			{
				outputs.push_back( out );
			}
		}
	}
}

void Shader::parameterHash( const Gaffer::Plug *parameterPlug, NetworkBuilder &network, IECore::MurmurHash &h ) const
{
	const Plug *inputPlug = parameterPlug->source<Plug>();
	if( inputPlug )
	{
		const Shader *n = IECore::runTimeCast<const Shader>( inputPlug->node() );
		if( n )
		{
			h.append( network.shaderHash( n ) );
			return;
		}
		// fall through to hash plug value
	}

	const ValuePlug *vplug = IECore::runTimeCast<const ValuePlug>( parameterPlug );
	if( vplug )
	{
		vplug->hash( h );
	}
	else
	{
		h.append( parameterPlug->typeId() );
	}
}

IECore::DataPtr Shader::parameterValue( const Gaffer::Plug *parameterPlug, NetworkBuilder &network ) const
{
	if( const Gaffer::ValuePlug *valuePlug = IECore::runTimeCast<const Gaffer::ValuePlug>( parameterPlug ) )
	{
		return Gaffer::CompoundDataPlug::extractDataFromPlug( valuePlug );
	}
	return 0;
}

//////////////////////////////////////////////////////////////////////////
// NetworkBuilder implementation
//////////////////////////////////////////////////////////////////////////

Shader::NetworkBuilder::NetworkBuilder( const Shader *rootNode )
	:	m_rootNode( rootNode )
{
}

IECore::MurmurHash Shader::NetworkBuilder::stateHash()
{
	return shaderHash( m_rootNode );
}

IECore::ConstObjectVectorPtr Shader::NetworkBuilder::state()
{
	if( !m_state )
	{
		m_state = new IECore::ObjectVector;
		shader( m_rootNode );
	}
	return m_state;
}

IECore::MurmurHash Shader::NetworkBuilder::shaderHash( const Shader *shaderNode )
{
	shaderNode = effectiveNode( shaderNode );
	if( !shaderNode )
	{
		IECore::MurmurHash h;
		h.append( Shader::staticTypeId() );
		return h;
	}

	ShaderAndHash &shaderAndHash = m_shaders[shaderNode];
	if( shaderAndHash.hash != IECore::MurmurHash() )
	{
		return shaderAndHash.hash;
	}

	shaderAndHash.hash.append( shaderNode->typeId() );
	shaderNode->namePlug()->hash( shaderAndHash.hash );
	shaderNode->typePlug()->hash( shaderAndHash.hash );

	for( InputPlugIterator it( shaderNode->parametersPlug() ); it!=it.end(); ++it )
	{
		shaderNode->parameterHash( *it, *this, shaderAndHash.hash );
	}

	return shaderAndHash.hash;
}

IECore::Shader *Shader::NetworkBuilder::shader( const Shader *shaderNode )
{
	shaderNode = effectiveNode( shaderNode );
	if( !shaderNode )
	{
		return 0;
	}

	ShaderAndHash &shaderAndHash = m_shaders[shaderNode];
	if( shaderAndHash.shader )
	{
		return shaderAndHash.shader;
	}

	shaderAndHash.shader = new IECore::Shader( shaderNode->namePlug()->getValue(), shaderNode->typePlug()->getValue() );
	for( InputPlugIterator it( shaderNode->parametersPlug() ); it!=it.end(); it++ )
	{
		IECore::DataPtr value = shaderNode->parameterValue( *it, *this );
		if( value )
		{
			shaderAndHash.shader->parameters()[(*it)->getName()] = value;
		}
	}

	m_state->members().push_back( shaderAndHash.shader );
	return shaderAndHash.shader;
}

const std::string &Shader::NetworkBuilder::shaderHandle( const Shader *shaderNode )
{
	IECore::Shader *s = shader( shaderNode );
	if( !s )
	{
		static std::string emptyString;
		return emptyString;
	}

	IECore::StringDataPtr handleData = s->parametersData()->member<IECore::StringData>( "__handle" );
	if( !handleData )
	{
		s->setType( "shader" );
		handleData = new IECore::StringData( boost::lexical_cast<std::string>( s ) );
		s->parameters()["__handle"] = handleData;
	}
	return handleData->readable();
}

const Shader *Shader::NetworkBuilder::effectiveNode( const Shader *shaderNode ) const
{
	while( shaderNode )
	{
		if( shaderNode->enabledPlug()->getValue() )
		{
			return shaderNode;
		}

		const Plug *correspondingInput = shaderNode->correspondingInput( shaderNode->outPlug() );
		if( !correspondingInput )
		{
			return NULL;
		}

		const Plug *source = correspondingInput->source<Plug>();
		if( source == correspondingInput )
		{
			return NULL;
		}

		shaderNode = source->ancestor<Shader>();
	}
	return NULL;
}
<commit_msg>corrected usage of source method<commit_after>//////////////////////////////////////////////////////////////////////////
//
//  Copyright (c) 2012, John Haddon. All rights reserved.
//  Copyright (c) 2013, Image Engine Design Inc. All rights reserved.
//
//  Redistribution and use in source and binary forms, with or without
//  modification, are permitted provided that the following conditions are
//  met:
//
//      * Redistributions of source code must retain the above
//        copyright notice, this list of conditions and the following
//        disclaimer.
//
//      * Redistributions in binary form must reproduce the above
//        copyright notice, this list of conditions and the following
//        disclaimer in the documentation and/or other materials provided with
//        the distribution.
//
//      * Neither the name of John Haddon nor the names of
//        any other contributors to this software may be used to endorse or
//        promote products derived from this software without specific prior
//        written permission.
//
//  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
//  IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
//  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
//  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
//  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
//  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
//  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
//  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
//  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
//  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
//////////////////////////////////////////////////////////////////////////

#include "boost/lexical_cast.hpp"

#include "Gaffer/TypedPlug.h"
#include "Gaffer/NumericPlug.h"
#include "Gaffer/CompoundDataPlug.h"

#include "GafferScene/Shader.h"

using namespace Imath;
using namespace GafferScene;
using namespace Gaffer;

IE_CORE_DEFINERUNTIMETYPED( Shader );

size_t Shader::g_firstPlugIndex = 0;

Shader::Shader( const std::string &name )
	:	DependencyNode( name )
{
	storeIndexOfNextChild( g_firstPlugIndex );
	addChild( new StringPlug( "name" ) );
	addChild( new StringPlug( "type" ) );
	addChild( new CompoundPlug( "parameters" ) );
	addChild( new BoolPlug( "enabled", Gaffer::Plug::In, true ) );
}

Shader::~Shader()
{
}

Gaffer::StringPlug *Shader::namePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

const Gaffer::StringPlug *Shader::namePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex );
}

Gaffer::StringPlug *Shader::typePlug()
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

const Gaffer::StringPlug *Shader::typePlug() const
{
	return getChild<StringPlug>( g_firstPlugIndex + 1 );
}

Gaffer::CompoundPlug *Shader::parametersPlug()
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 );
}

const Gaffer::CompoundPlug *Shader::parametersPlug() const
{
	return getChild<CompoundPlug>( g_firstPlugIndex + 2 );
}

Gaffer::Plug *Shader::outPlug()
{
	// not getting by index, because it is created by the
	// derived classes in loadShader().
	return getChild<Plug>( "out" );
}

const Gaffer::Plug *Shader::outPlug() const
{
	return getChild<Plug>( "out" );
}

Gaffer::BoolPlug *Shader::enabledPlug()
{
	return getChild<BoolPlug>( g_firstPlugIndex + 3 );
}

const Gaffer::BoolPlug *Shader::enabledPlug() const
{
	return getChild<BoolPlug>( g_firstPlugIndex + 3 );
}

IECore::MurmurHash Shader::stateHash() const
{
	NetworkBuilder networkBuilder( this );
	return networkBuilder.stateHash();
}

void Shader::stateHash( IECore::MurmurHash &h ) const
{
	h.append( stateHash() );
}

IECore::ConstObjectVectorPtr Shader::state() const
{
	NetworkBuilder networkBuilder( this );
	return networkBuilder.state();
}

void Shader::affects( const Gaffer::Plug *input, AffectedPlugsContainer &outputs ) const
{
	DependencyNode::affects( input, outputs );

	if( parametersPlug()->isAncestorOf( input ) || input == enabledPlug() )
	{
		const Plug *out = outPlug();
		if( out )
		{
			if( out->isInstanceOf( CompoundPlug::staticTypeId() ) )
			{
				for( RecursiveValuePlugIterator it( out ); it != it.end(); it++ )
				{
					if( !(*it)->isInstanceOf( CompoundPlug::staticTypeId() ) )
					{
						outputs.push_back( it->get() );
					}
				}
			}
			else
			{
				outputs.push_back( out );
			}
		}
	}
}

void Shader::parameterHash( const Gaffer::Plug *parameterPlug, NetworkBuilder &network, IECore::MurmurHash &h ) const
{
	const Plug *inputPlug = parameterPlug->source<Plug>();
	if( inputPlug != parameterPlug )
	{
		const Shader *n = IECore::runTimeCast<const Shader>( inputPlug->node() );
		if( n )
		{
			h.append( network.shaderHash( n ) );
			return;
		}
		// fall through to hash plug value
	}

	const ValuePlug *vplug = IECore::runTimeCast<const ValuePlug>( parameterPlug );
	if( vplug )
	{
		vplug->hash( h );
	}
	else
	{
		h.append( parameterPlug->typeId() );
	}
}

IECore::DataPtr Shader::parameterValue( const Gaffer::Plug *parameterPlug, NetworkBuilder &network ) const
{
	if( const Gaffer::ValuePlug *valuePlug = IECore::runTimeCast<const Gaffer::ValuePlug>( parameterPlug ) )
	{
		return Gaffer::CompoundDataPlug::extractDataFromPlug( valuePlug );
	}
	return 0;
}

//////////////////////////////////////////////////////////////////////////
// NetworkBuilder implementation
//////////////////////////////////////////////////////////////////////////

Shader::NetworkBuilder::NetworkBuilder( const Shader *rootNode )
	:	m_rootNode( rootNode )
{
}

IECore::MurmurHash Shader::NetworkBuilder::stateHash()
{
	return shaderHash( m_rootNode );
}

IECore::ConstObjectVectorPtr Shader::NetworkBuilder::state()
{
	if( !m_state )
	{
		m_state = new IECore::ObjectVector;
		shader( m_rootNode );
	}
	return m_state;
}

IECore::MurmurHash Shader::NetworkBuilder::shaderHash( const Shader *shaderNode )
{
	shaderNode = effectiveNode( shaderNode );
	if( !shaderNode )
	{
		IECore::MurmurHash h;
		h.append( Shader::staticTypeId() );
		return h;
	}

	ShaderAndHash &shaderAndHash = m_shaders[shaderNode];
	if( shaderAndHash.hash != IECore::MurmurHash() )
	{
		return shaderAndHash.hash;
	}

	shaderAndHash.hash.append( shaderNode->typeId() );
	shaderNode->namePlug()->hash( shaderAndHash.hash );
	shaderNode->typePlug()->hash( shaderAndHash.hash );

	for( InputPlugIterator it( shaderNode->parametersPlug() ); it!=it.end(); ++it )
	{
		shaderNode->parameterHash( *it, *this, shaderAndHash.hash );
	}

	return shaderAndHash.hash;
}

IECore::Shader *Shader::NetworkBuilder::shader( const Shader *shaderNode )
{
	shaderNode = effectiveNode( shaderNode );
	if( !shaderNode )
	{
		return 0;
	}

	ShaderAndHash &shaderAndHash = m_shaders[shaderNode];
	if( shaderAndHash.shader )
	{
		return shaderAndHash.shader;
	}

	shaderAndHash.shader = new IECore::Shader( shaderNode->namePlug()->getValue(), shaderNode->typePlug()->getValue() );
	for( InputPlugIterator it( shaderNode->parametersPlug() ); it!=it.end(); it++ )
	{
		IECore::DataPtr value = shaderNode->parameterValue( *it, *this );
		if( value )
		{
			shaderAndHash.shader->parameters()[(*it)->getName()] = value;
		}
	}

	m_state->members().push_back( shaderAndHash.shader );
	return shaderAndHash.shader;
}

const std::string &Shader::NetworkBuilder::shaderHandle( const Shader *shaderNode )
{
	IECore::Shader *s = shader( shaderNode );
	if( !s )
	{
		static std::string emptyString;
		return emptyString;
	}

	IECore::StringDataPtr handleData = s->parametersData()->member<IECore::StringData>( "__handle" );
	if( !handleData )
	{
		s->setType( "shader" );
		handleData = new IECore::StringData( boost::lexical_cast<std::string>( s ) );
		s->parameters()["__handle"] = handleData;
	}
	return handleData->readable();
}

const Shader *Shader::NetworkBuilder::effectiveNode( const Shader *shaderNode ) const
{
	while( shaderNode )
	{
		if( shaderNode->enabledPlug()->getValue() )
		{
			return shaderNode;
		}

		const Plug *correspondingInput = shaderNode->correspondingInput( shaderNode->outPlug() );
		if( !correspondingInput )
		{
			return NULL;
		}

		const Plug *source = correspondingInput->source<Plug>();
		if( source == correspondingInput )
		{
			return NULL;
		}

		shaderNode = source->ancestor<Shader>();
	}
	return NULL;
}
<|endoftext|>