<commit_before>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Hammad Mazhar
// =============================================================================
//
// ChronoParallel unit test for MPR collision detection
// =============================================================================
// not used but prevents compilation errors with cuda 7 RC
#include <thrust/transform.h>

#include <stdio.h>
#include <vector>
#include <cmath>
#include <omp.h>
#include "unit_testing.h"
#include "chrono_parallel/constraints/ChConstraintRigidRigid.h"
#include "collision/ChCCollisionModel.h"
#include "core/ChMathematics.h"

#include "chrono_utils/ChUtilsCreators.h"
#include "chrono_utils/ChUtilsInputOutput.h"
#include <blaze/math/CompressedMatrix.h>
#include <blaze/math/DynamicVector.h>
//#include <blaze/math/SymmetricMatrix.h>
using blaze::CompressedMatrix;
using blaze::DynamicVector;
using namespace std;
using namespace chrono;
using namespace chrono::collision;
using namespace chrono::utils;
double timestep = .001;
double factor = 1.0 / timestep;

int main(int argc, char* argv[]) {
  omp_set_num_threads(8);
  ChSystemParallelDVI* system_gpu = new ChSystemParallelDVI;
  system_gpu->SetIntegrationType(ChSystem::INT_ANITESCU);

  std::stringstream ss;
  ss << "container_checkpoint_50_settled.txt";

  system_gpu->ChangeCollisionSystem(COLLSYS_BULLET_PARALLEL);
  system_gpu->SetStep(timestep);
  system_gpu->SetMaxPenetrationRecoverySpeed(10000);
  utils::ReadCheckpoint(system_gpu, ss.str());
  system_gpu->AssembleSystem();
  ChContactContainer* container = (ChContactContainer*)system_gpu->GetContactContainer();

  std::vector<ChLcpConstraint*>& mconstraints = system_gpu->GetLcpSystemDescriptor()->GetConstraintsList();
  std::vector<ChLcpVariables*>& mvariables = system_gpu->GetLcpSystemDescriptor()->GetVariablesList();
  size_t nOfVars = mvariables.size();
  size_t nOfConstraints = mconstraints.size();

  ChMatrixDynamic<> mb(nOfConstraints, 1);

  //#########
  for (unsigned int ic = 0; ic < nOfConstraints; ic++) {
    mconstraints[ic]->Update_auxiliary();
  }

  // Average all g_i for the triplet of contact constraints n,u,v.
  //  Can be used for the fixed point phase and/or by preconditioner.
  int j_friction_comp = 0;
  double gi_values[3];
  for (unsigned int ic = 0; ic < nOfConstraints; ic++) {
    if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) {
      gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
      j_friction_comp++;
      if (j_friction_comp == 3) {
        double average_g_i = (gi_values[0] + gi_values[1] + gi_values[2]) / 3.0;
        mconstraints[ic - 2]->Set_g_i(average_g_i);
        mconstraints[ic - 1]->Set_g_i(average_g_i);
        mconstraints[ic - 0]->Set_g_i(average_g_i);
        j_friction_comp = 0;
      }
    }
  }

  for (unsigned int iv = 0; iv < nOfVars; iv++) {
    if (mvariables[iv]->IsActive()) {
      mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb());  // q = [M]'*fb
    }
  }
  ChMatrixDynamic<> mb_tmp(nOfConstraints, 1);
  int s_i = 0;
  for (unsigned int ic = 0; ic < nOfConstraints; ic++)
    if (mconstraints[ic]->IsActive()) {
      mb(s_i, 0) = -mconstraints[ic]->Compute_Cq_q();
      ++s_i;
    }
  system_gpu->GetLcpSystemDescriptor()->BuildBiVector(mb_tmp);  // b_i   =   -c   = phi/h
  mb.MatrDec(mb_tmp);
  ChLcpSystemDescriptor* sysd = system_gpu->GetLcpSystemDescriptor();

  // ChMatrixDynamic<> mq;
  // sysd->FromVariablesToVector(mq, true);
  //#########
  chrono::ChSparseMatrix mdM;
  chrono::ChSparseMatrix mdCq;
  chrono::ChSparseMatrix mdE;
  chrono::ChMatrixDynamic<double> mdf;
  chrono::ChMatrixDynamic<double> mdb;
  chrono::ChMatrixDynamic<double> mdfric;
  chrono::ChMatrixDynamic<double> mdgamma;
  sysd->ConvertToMatrixForm(&mdCq, &mdM, &mdE, &mdf, &mdb, &mdfric);

  cout << mdM.GetRows() << " " << mdM.GetColumns() << endl;
  cout << mdCq.GetRows() << " " << mdCq.GetColumns() << endl;

  //   int mn_c = 0;
  //   for (unsigned int ic = 0; ic < mconstraints.size(); ic++) {
  //      if (mconstraints[ic]->IsActive())
  //         if (!((mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)))
  //            if (!((dynamic_cast<ChLcpConstraintTwoFrictionT*>(mconstraints[ic])))) {
  //               mn_c++;
  //            }
  //   }

  // Count active variables, by scanning through all variable blocks,
  // and set offsets

  int n_q = sysd->CountActiveVariables();

  CompressedMatrix<double> Mass_inv(n_q, n_q), D_t(mdCq.GetRows(), mdCq.GetColumns());
  CompressedMatrix<double> Mass_invsqt(n_q, n_q);

  for (int ii = 0; ii < mdM.GetRows(); ii++) {
    for (int jj = 0; jj < mdM.GetColumns(); jj++) {
      double elVal = mdM.GetElement(ii, jj);
      if (elVal || (ii + 1 == mdM.GetRows() && jj + 1 == mdM.GetColumns())) {
        Mass_inv.insert(ii, jj, 1.0 / elVal);
        Mass_invsqt.insert(ii, jj, 1.0 / sqrt(elVal));
      }
    }
  }

  for (int ii = 0; ii < mdCq.GetRows(); ii++) {
    for (int jj = 0; jj < mdCq.GetColumns(); jj++) {
      double elVal = mdCq.GetElement(ii, jj);
      if (elVal || (ii + 1 == mdCq.GetRows() && jj + 1 == mdCq.GetColumns())) {
        D_t.insert(ii, jj, elVal);
      }
    }
  }
  CompressedMatrix<double> D = trans(D_t);
  CompressedMatrix<double> MinvD = Mass_inv * D;
  CompressedMatrix<double> MinvsqrtD = Mass_invsqt * D;
  CompressedMatrix<double> MinvsqrtD_t = trans(MinvsqrtD);
  CompressedMatrix<double> N = D_t * Mass_inv * D;
  // blaze::SymmetricMatrix<CompressedMatrix<double> > N_sym = D_t * Mass_inv * D;
  //
  //      cout << D.rows() << " " << D.columns() << endl;
  //      cout << D_t.rows() << " " << D_t.columns() << endl;
  //      cout << Mass_inv.rows() << " " << Mass_inv.columns() << endl;

  DynamicVector<double> rhs_vector(nOfConstraints);

  for (unsigned int ic = 0; ic < mconstraints.size(); ic++) {
    rhs_vector[ic] = mb(ic, 0);
  }

  cout << N.rows() << " " << N.columns() << endl;

  ChTimer<double> timer;
  timer.start();
  DynamicVector<double> result_1 = MinvsqrtD_t * (MinvsqrtD * rhs_vector);
  timer.stop();
  std::cout << "MinvsqrtD_t * MinvsqrtD * rhs_vector: " << timer() << std::endl;
  timer.start();
  DynamicVector<double> result_2 = N * rhs_vector;
  timer.stop();
  std::cout << "N * rhs_vector: " << timer() << std::endl;
  // timer.start();
  // DynamicVector<double> result_3 = N_sym * rhs_vector;
  // timer.stop();
  // std::cout << "N_sym * rhs_vector: " << timer() << std::endl;
  timer.start();
  DynamicVector<double> result_4 = D_t * (MinvD * rhs_vector);
  timer.stop();
  std::cout << "D_t * MinvD * rhs_vector: " << timer() << std::endl;

  return 0;
}
<commit_msg>using namespace std will cause issues when using namespace chrono because of std::chrono<commit_after>// =============================================================================
// PROJECT CHRONO - http://projectchrono.org
//
// Copyright (c) 2014 projectchrono.org
// All right reserved.
//
// Use of this source code is governed by a BSD-style license that can be found
// in the LICENSE file at the top level of the distribution and at
// http://projectchrono.org/license-chrono.txt.
//
// =============================================================================
// Authors: Hammad Mazhar
// =============================================================================
//
// ChronoParallel unit test for MPR collision detection
// =============================================================================
// not used but prevents compilation errors with cuda 7 RC
#include <thrust/transform.h>

#include <stdio.h>
#include <vector>
#include <cmath>
#include <omp.h>
#include "unit_testing.h"
#include "chrono_parallel/constraints/ChConstraintRigidRigid.h"
#include "collision/ChCCollisionModel.h"
#include "core/ChMathematics.h"

#include "chrono_utils/ChUtilsCreators.h"
#include "chrono_utils/ChUtilsInputOutput.h"
#include <blaze/math/CompressedMatrix.h>
#include <blaze/math/DynamicVector.h>
//#include <blaze/math/SymmetricMatrix.h>
using blaze::CompressedMatrix;
using blaze::DynamicVector;
using namespace chrono;
using namespace chrono::collision;
using namespace chrono::utils;
double timestep = .001;
double factor = 1.0 / timestep;

int main(int argc, char* argv[]) {
  omp_set_num_threads(8);
  ChSystemParallelDVI* system_gpu = new ChSystemParallelDVI;
  system_gpu->SetIntegrationType(ChSystem::INT_ANITESCU);

  std::stringstream ss;
  ss << "container_checkpoint_50_settled.txt";

  system_gpu->ChangeCollisionSystem(COLLSYS_BULLET_PARALLEL);
  system_gpu->SetStep(timestep);
  system_gpu->SetMaxPenetrationRecoverySpeed(10000);
  utils::ReadCheckpoint(system_gpu, ss.str());
  system_gpu->AssembleSystem();
  ChContactContainer* container = (ChContactContainer*)system_gpu->GetContactContainer();

  std::vector<ChLcpConstraint*>& mconstraints = system_gpu->GetLcpSystemDescriptor()->GetConstraintsList();
  std::vector<ChLcpVariables*>& mvariables = system_gpu->GetLcpSystemDescriptor()->GetVariablesList();
  size_t nOfVars = mvariables.size();
  size_t nOfConstraints = mconstraints.size();

  ChMatrixDynamic<> mb(nOfConstraints, 1);

  //#########
  for (unsigned int ic = 0; ic < nOfConstraints; ic++) {
    mconstraints[ic]->Update_auxiliary();
  }

  // Average all g_i for the triplet of contact constraints n,u,v.
  //  Can be used for the fixed point phase and/or by preconditioner.
  int j_friction_comp = 0;
  double gi_values[3];
  for (unsigned int ic = 0; ic < nOfConstraints; ic++) {
    if (mconstraints[ic]->GetMode() == CONSTRAINT_FRIC) {
      gi_values[j_friction_comp] = mconstraints[ic]->Get_g_i();
      j_friction_comp++;
      if (j_friction_comp == 3) {
        double average_g_i = (gi_values[0] + gi_values[1] + gi_values[2]) / 3.0;
        mconstraints[ic - 2]->Set_g_i(average_g_i);
        mconstraints[ic - 1]->Set_g_i(average_g_i);
        mconstraints[ic - 0]->Set_g_i(average_g_i);
        j_friction_comp = 0;
      }
    }
  }

  for (unsigned int iv = 0; iv < nOfVars; iv++) {
    if (mvariables[iv]->IsActive()) {
      mvariables[iv]->Compute_invMb_v(mvariables[iv]->Get_qb(), mvariables[iv]->Get_fb());  // q = [M]'*fb
    }
  }
  ChMatrixDynamic<> mb_tmp(nOfConstraints, 1);
  int s_i = 0;
  for (unsigned int ic = 0; ic < nOfConstraints; ic++)
    if (mconstraints[ic]->IsActive()) {
      mb(s_i, 0) = -mconstraints[ic]->Compute_Cq_q();
      ++s_i;
    }
  system_gpu->GetLcpSystemDescriptor()->BuildBiVector(mb_tmp);  // b_i   =   -c   = phi/h
  mb.MatrDec(mb_tmp);
  ChLcpSystemDescriptor* sysd = system_gpu->GetLcpSystemDescriptor();

  // ChMatrixDynamic<> mq;
  // sysd->FromVariablesToVector(mq, true);
  //#########
  chrono::ChSparseMatrix mdM;
  chrono::ChSparseMatrix mdCq;
  chrono::ChSparseMatrix mdE;
  chrono::ChMatrixDynamic<double> mdf;
  chrono::ChMatrixDynamic<double> mdb;
  chrono::ChMatrixDynamic<double> mdfric;
  chrono::ChMatrixDynamic<double> mdgamma;
  sysd->ConvertToMatrixForm(&mdCq, &mdM, &mdE, &mdf, &mdb, &mdfric);

  std::cout << mdM.GetRows() << " " << mdM.GetColumns() << std::endl;
  std::cout << mdCq.GetRows() << " " << mdCq.GetColumns() << std::endl;

  //   int mn_c = 0;
  //   for (unsigned int ic = 0; ic < mconstraints.size(); ic++) {
  //      if (mconstraints[ic]->IsActive())
  //         if (!((mconstraints[ic]->GetMode() == CONSTRAINT_FRIC)))
  //            if (!((dynamic_cast<ChLcpConstraintTwoFrictionT*>(mconstraints[ic])))) {
  //               mn_c++;
  //            }
  //   }

  // Count active variables, by scanning through all variable blocks,
  // and set offsets

  int n_q = sysd->CountActiveVariables();

  CompressedMatrix<double> Mass_inv(n_q, n_q), D_t(mdCq.GetRows(), mdCq.GetColumns());
  CompressedMatrix<double> Mass_invsqt(n_q, n_q);

  for (int ii = 0; ii < mdM.GetRows(); ii++) {
    for (int jj = 0; jj < mdM.GetColumns(); jj++) {
      double elVal = mdM.GetElement(ii, jj);
      if (elVal || (ii + 1 == mdM.GetRows() && jj + 1 == mdM.GetColumns())) {
        Mass_inv.insert(ii, jj, 1.0 / elVal);
        Mass_invsqt.insert(ii, jj, 1.0 / sqrt(elVal));
      }
    }
  }

  for (int ii = 0; ii < mdCq.GetRows(); ii++) {
    for (int jj = 0; jj < mdCq.GetColumns(); jj++) {
      double elVal = mdCq.GetElement(ii, jj);
      if (elVal || (ii + 1 == mdCq.GetRows() && jj + 1 == mdCq.GetColumns())) {
        D_t.insert(ii, jj, elVal);
      }
    }
  }
  CompressedMatrix<double> D = trans(D_t);
  CompressedMatrix<double> MinvD = Mass_inv * D;
  CompressedMatrix<double> MinvsqrtD = Mass_invsqt * D;
  CompressedMatrix<double> MinvsqrtD_t = trans(MinvsqrtD);
  CompressedMatrix<double> N = D_t * Mass_inv * D;
  // blaze::SymmetricMatrix<CompressedMatrix<double> > N_sym = D_t * Mass_inv * D;
  //
  //      cout << D.rows() << " " << D.columns() << endl;
  //      cout << D_t.rows() << " " << D_t.columns() << endl;
  //      cout << Mass_inv.rows() << " " << Mass_inv.columns() << endl;

  DynamicVector<double> rhs_vector(nOfConstraints);

  for (unsigned int ic = 0; ic < mconstraints.size(); ic++) {
    rhs_vector[ic] = mb(ic, 0);
  }

  std::cout << N.rows() << " " << N.columns() << std::endl;

  ChTimer<double> timer;
  timer.start();
  DynamicVector<double> result_1 = MinvsqrtD_t * (MinvsqrtD * rhs_vector);
  timer.stop();
  std::cout << "MinvsqrtD_t * MinvsqrtD * rhs_vector: " << timer() << std::endl;
  timer.start();
  DynamicVector<double> result_2 = N * rhs_vector;
  timer.stop();
  std::cout << "N * rhs_vector: " << timer() << std::endl;
  // timer.start();
  // DynamicVector<double> result_3 = N_sym * rhs_vector;
  // timer.stop();
  // std::cout << "N_sym * rhs_vector: " << timer() << std::endl;
  timer.start();
  DynamicVector<double> result_4 = D_t * (MinvD * rhs_vector);
  timer.stop();
  std::cout << "D_t * MinvD * rhs_vector: " << timer() << std::endl;

  return 0;
}
<|endoftext|>


<commit_before>// Copyright 2019 Google LLC. All Rights Reserved.
//
// 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
//
//     https://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 <cmath>
#include <complex>
#include <cstdint>
#include <sstream>

#include "gtest/gtest.h"

#include "../lib/circuit_reader.h"
#include "../lib/fuser_basic.h"
#include "../lib/gate.h"
#include "../lib/io.h"
#include "../lib/parfor.h"
#include "../lib/run_qsim.h"
#include "../lib/simulator_avx.h"

namespace qsim {

constexpr char provider[] = "run_qsim_test";

constexpr char circuit_string[] =
R"(4
0 h 0
0 h 1
0 h 2
0 h 3
1 cz 0 1
1 cz 2 3
2 t 0
2 x 1
2 y 2
2 t 3
3 y 0
3 cz 1 2
3 x 3
4 t 1
4 t 2
5 cz 1 2
6 x 1
6 y 2
7 cz 1 2
8 t 1
8 t 2
9 cz 0 1
9 cz 2 3
10 h 0
10 h 1
10 h 2
10 h 3
)";

TEST(QSimRunner, RimQSim1) {
  std::stringstream ss(circuit_string);
  Circuit<Gate<float>> circuit;

  EXPECT_EQ(CircuitReader<IO>::FromStream(99, provider, ss, circuit), true);
  EXPECT_EQ(circuit.num_qubits, 4);
  EXPECT_EQ(circuit.gates.size(), 27);

  using Simulator = SimulatorAVX<ParallelFor>;
  using StateSpace = Simulator::StateSpace;
  using State = StateSpace::State;
  using Runner = QSimRunner<IO, BasicGateFuser<Gate<float>>, Simulator>;

  float entropy;

  auto measure = [&entropy](
      unsigned k, const StateSpace& state_space, const State& state) {
    // Calculate entropy.

    entropy = 0;

    for (uint64_t i = 0; i < state_space.Size(state); ++i) {
      auto ampl = state_space.GetAmpl(state, i);
      float p = std::norm(ampl);
      entropy -= p * std::log(p);
    }
  };

  Runner::Parameter param;
  param.num_threads = 1;
  param.verbosity = 0;

  EXPECT_EQ(Runner::Run(param, 99, circuit, measure), true);

  EXPECT_NEAR(entropy, 2.2192848, 1e-6);
}

TEST(QSimRunner, RimQSim2) {
  std::stringstream ss(circuit_string);
  Circuit<Gate<float>> circuit;

  EXPECT_EQ(CircuitReader<IO>::FromStream(99, provider, ss, circuit), true);
  EXPECT_EQ(circuit.num_qubits, 4);
  EXPECT_EQ(circuit.gates.size(), 27);

  using Simulator = SimulatorAVX<ParallelFor>;
  using StateSpace = Simulator::StateSpace;
  using State = StateSpace::State;
  using Runner = QSimRunner<IO, BasicGateFuser<Gate<float>>, Simulator>;

  StateSpace state_space(circuit.num_qubits, 1);
  State state = state_space.CreateState();

  EXPECT_EQ(state_space.IsNull(state), false);

  state_space.SetStateZero(state);

  Runner::Parameter param;
  param.num_threads = 1;
  param.verbosity = 0;

  EXPECT_EQ(Runner::Run(param, 99, circuit, state), true);

  // Calculate entropy.

  float entropy = 0;

  for (uint64_t i = 0; i < state_space.Size(state); ++i) {
    auto ampl = state_space.GetAmpl(state, i);
    float p = std::norm(ampl);
    entropy -= p * std::log(p);
  }

  EXPECT_NEAR(entropy, 2.2192848, 1e-6);
}

}  // namespace qsim

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<commit_msg>Add another helper function to run qsim.<commit_after>// Copyright 2019 Google LLC. All Rights Reserved.
//
// 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
//
//     https://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 <cmath>
#include <complex>
#include <cstdint>
#include <sstream>

#include "gtest/gtest.h"

#include "../lib/circuit_reader.h"
#include "../lib/fuser_basic.h"
#include "../lib/gate.h"
#include "../lib/io.h"
#include "../lib/parfor.h"
#include "../lib/run_qsim.h"
#include "../lib/simulator_avx.h"

namespace qsim {

constexpr char provider[] = "run_qsim_test";

constexpr char circuit_string[] =
R"(4
0 h 0
0 h 1
0 h 2
0 h 3
1 cz 0 1
1 cz 2 3
2 t 0
2 x 1
2 y 2
2 t 3
3 y 0
3 cz 1 2
3 x 3
4 t 1
4 t 2
5 cz 1 2
6 x 1
6 y 2
7 cz 1 2
8 t 1
8 t 2
9 cz 0 1
9 cz 2 3
10 h 0
10 h 1
10 h 2
10 h 3
)";

TEST(QSimRunner, RunQSim1) {
  std::stringstream ss(circuit_string);
  Circuit<Gate<float>> circuit;

  EXPECT_EQ(CircuitReader<IO>::FromStream(99, provider, ss, circuit), true);
  EXPECT_EQ(circuit.num_qubits, 4);
  EXPECT_EQ(circuit.gates.size(), 27);

  using Simulator = SimulatorAVX<ParallelFor>;
  using StateSpace = Simulator::StateSpace;
  using State = StateSpace::State;
  using Runner = QSimRunner<IO, BasicGateFuser<Gate<float>>, Simulator>;

  float entropy;

  auto measure = [&entropy](
      unsigned k, const StateSpace& state_space, const State& state) {
    // Calculate entropy.

    entropy = 0;

    for (uint64_t i = 0; i < state_space.Size(state); ++i) {
      auto ampl = state_space.GetAmpl(state, i);
      float p = std::norm(ampl);
      entropy -= p * std::log(p);
    }
  };

  Runner::Parameter param;
  param.num_threads = 1;
  param.verbosity = 0;

  EXPECT_EQ(Runner::Run(param, 99, circuit, measure), true);

  EXPECT_NEAR(entropy, 2.2192848, 1e-6);
}

TEST(QSimRunner, RunQSim2) {
  std::stringstream ss(circuit_string);
  Circuit<Gate<float>> circuit;

  EXPECT_EQ(CircuitReader<IO>::FromStream(99, provider, ss, circuit), true);
  EXPECT_EQ(circuit.num_qubits, 4);
  EXPECT_EQ(circuit.gates.size(), 27);

  using Simulator = SimulatorAVX<ParallelFor>;
  using StateSpace = Simulator::StateSpace;
  using State = StateSpace::State;
  using Runner = QSimRunner<IO, BasicGateFuser<Gate<float>>, Simulator>;

  StateSpace state_space(circuit.num_qubits, 1);
  State state = state_space.CreateState();

  EXPECT_EQ(state_space.IsNull(state), false);

  state_space.SetStateZero(state);

  Runner::Parameter param;
  param.num_threads = 1;
  param.verbosity = 0;

  EXPECT_EQ(Runner::Run(param, 99, circuit, state), true);

  // Calculate entropy.

  float entropy = 0;

  for (uint64_t i = 0; i < state_space.Size(state); ++i) {
    auto ampl = state_space.GetAmpl(state, i);
    float p = std::norm(ampl);
    entropy -= p * std::log(p);
  }

  EXPECT_NEAR(entropy, 2.2192848, 1e-6);
}

}  // namespace qsim

int main(int argc, char** argv) {
  ::testing::InitGoogleTest(&argc, argv);
  return RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>/*
 * GAMS - General Algebraic Modeling System C++ API
 *
 * Copyright (c) 2017-2018 GAMS Software GmbH <support@gams.com>
 * Copyright (c) 2017-2018 GAMS Development Corp. <support@gams.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "transport.h"

#include <ostream>

using namespace gams;
using namespace std;

/// \file transport.cpp
/// \brief Wrapper class implementation for GAMS trnsport model
Transport::Transport(GAMSWorkspace ws)
    : fws(ws),
      job(fws.addJobFromString(getModelSource())),
      fopt(fws.addOptions())
{
    fws = ws;
    fopt = ws.addOptions();

    fDbIn1 = ws.addDatabase("", "dbIn1");
    fDbIn2 = ws.addDatabase("", "dbIn2");

    // TODO(AF) add enum to GAMSOptions
    fopt.setSolveLink(GAMSOptions::ESolveLink::LoadLibrary);
    fopt.setAllModelTypes("Cplex");
    fopt.setDefine("dbOut1", "dbOut1");

    fi = fDbIn1.addSet("i", "canning plants");
    fj = fDbIn1.addSet("j", "markets");
    fa = fDbIn1.addParameter("a", "capacity of plant i in cases", fi);
    fb = fDbIn1.addParameter("b", "demand at market j in cases", fj);
    fd = fDbIn1.addParameter("d", "distance in thousands of miles", fi, fj);
    ff = fDbIn2.addParameter("f", "freight in dollars per case per thousand miles");

    job = ws.addJobFromString(getModelSource());
}

void Transport::run(GAMSCheckpoint checkpoint, ostream &output)
{
    if (!fDbIn1.checkDomains())
        throw GAMSException("Domain Errors in Database 1");
    if (!fDbIn2.checkDomains())
        throw GAMSException("Domain Errors in Database 2");

    vector<GAMSDatabase> dbs {fDbIn1, fDbIn2};
    job.run(fopt, checkpoint, output, false, dbs);

    fDbOut1 = fws.addDatabaseFromGDX(fopt.getDefine("dbOut1") + ".gdx");
    fx = fDbOut1.getVariable("x");
    fz = fDbOut1.getVariable("z");
}

string Transport::getModelSource()
{
    return  "  Sets                                                                     \n"
            "       i   canning plants                                                  \n"
            "       j   markets                                                         \n"
            "                                                                           \n"
            "  Parameters                                                               \n"
            "       a(i)   capacity of plant i in cases                                 \n"
            "       b(j)   demand at market j in cases                                  \n"
            "       d(i,j) distance in thousands of miles                               \n"
            "  Scalar f  freight in dollars per case per thousand miles;                \n"
            "                                                                           \n"
            "$if not set dbIn1 $abort 'no file name for in-database 1 file provided'    \n"
            "$gdxin %dbIn1%                                                             \n"
            "$load i j a b d                                                            \n"
            "                                                                           \n"
            "$if not set dbIn2 $abort 'no file name for in-database 2 file provided'    \n"
            "$gdxin %dbIn2%                                                             \n"
            "$load f                                                                    \n"
            "$gdxin                                                                     \n"
            "                                                                           \n"
            "  Parameter c(i,j)  transport cost in thousands of dollars per case ;      \n"
            "                                                                           \n"
            "            c(i,j) = f * d(i,j) / 1000 ;                                   \n"
            "                                                                           \n"
            "  Variables                                                                \n"
            "       x(i,j)  shipment quantities in cases                                \n"
            "       z       total transportation costs in thousands of dollars ;        \n"
            "                                                                           \n"
            "  Positive Variable x ;                                                    \n"
            "                                                                           \n"
            "  Equations                                                                \n"
            "       cost        define objective function                               \n"
            "       supply(i)   observe supply limit at plant i                         \n"
            "       demand(j)   satisfy demand at market j ;                            \n"
            "                                                                           \n"
            "  cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;                       \n"
            "                                                                           \n"
            "  supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;                               \n"
            "                                                                           \n"
            "  demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;                               \n"
            "                                                                           \n"
            "  Model transport /all/ ;                                                  \n"
            "                                                                           \n"
            "  Solve transport using lp minimizing z ;                                  \n"
            "                                                                           \n"
            "$if not set dbOut1 $abort 'no file name for out-database 1 file provided'  \n"
            "  execute_unload '%dbOut1%', x, z;                                         \n";
}
<commit_msg>obsolete TODO<commit_after>/*
 * GAMS - General Algebraic Modeling System C++ API
 *
 * Copyright (c) 2017-2018 GAMS Software GmbH <support@gams.com>
 * Copyright (c) 2017-2018 GAMS Development Corp. <support@gams.com>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "transport.h"

#include <ostream>

using namespace gams;
using namespace std;

/// \file transport.cpp
/// \brief Wrapper class implementation for GAMS trnsport model
Transport::Transport(GAMSWorkspace ws)
    : fws(ws),
      job(fws.addJobFromString(getModelSource())),
      fopt(fws.addOptions())
{
    fws = ws;
    fopt = ws.addOptions();

    fDbIn1 = ws.addDatabase("", "dbIn1");
    fDbIn2 = ws.addDatabase("", "dbIn2");

    fopt.setSolveLink(GAMSOptions::ESolveLink::LoadLibrary);
    fopt.setAllModelTypes("Cplex");
    fopt.setDefine("dbOut1", "dbOut1");

    fi = fDbIn1.addSet("i", "canning plants");
    fj = fDbIn1.addSet("j", "markets");
    fa = fDbIn1.addParameter("a", "capacity of plant i in cases", fi);
    fb = fDbIn1.addParameter("b", "demand at market j in cases", fj);
    fd = fDbIn1.addParameter("d", "distance in thousands of miles", fi, fj);
    ff = fDbIn2.addParameter("f", "freight in dollars per case per thousand miles");

    job = ws.addJobFromString(getModelSource());
}

void Transport::run(GAMSCheckpoint checkpoint, ostream &output)
{
    if (!fDbIn1.checkDomains())
        throw GAMSException("Domain Errors in Database 1");
    if (!fDbIn2.checkDomains())
        throw GAMSException("Domain Errors in Database 2");

    vector<GAMSDatabase> dbs {fDbIn1, fDbIn2};
    job.run(fopt, checkpoint, output, false, dbs);

    fDbOut1 = fws.addDatabaseFromGDX(fopt.getDefine("dbOut1") + ".gdx");
    fx = fDbOut1.getVariable("x");
    fz = fDbOut1.getVariable("z");
}

string Transport::getModelSource()
{
    return  "  Sets                                                                     \n"
            "       i   canning plants                                                  \n"
            "       j   markets                                                         \n"
            "                                                                           \n"
            "  Parameters                                                               \n"
            "       a(i)   capacity of plant i in cases                                 \n"
            "       b(j)   demand at market j in cases                                  \n"
            "       d(i,j) distance in thousands of miles                               \n"
            "  Scalar f  freight in dollars per case per thousand miles;                \n"
            "                                                                           \n"
            "$if not set dbIn1 $abort 'no file name for in-database 1 file provided'    \n"
            "$gdxin %dbIn1%                                                             \n"
            "$load i j a b d                                                            \n"
            "                                                                           \n"
            "$if not set dbIn2 $abort 'no file name for in-database 2 file provided'    \n"
            "$gdxin %dbIn2%                                                             \n"
            "$load f                                                                    \n"
            "$gdxin                                                                     \n"
            "                                                                           \n"
            "  Parameter c(i,j)  transport cost in thousands of dollars per case ;      \n"
            "                                                                           \n"
            "            c(i,j) = f * d(i,j) / 1000 ;                                   \n"
            "                                                                           \n"
            "  Variables                                                                \n"
            "       x(i,j)  shipment quantities in cases                                \n"
            "       z       total transportation costs in thousands of dollars ;        \n"
            "                                                                           \n"
            "  Positive Variable x ;                                                    \n"
            "                                                                           \n"
            "  Equations                                                                \n"
            "       cost        define objective function                               \n"
            "       supply(i)   observe supply limit at plant i                         \n"
            "       demand(j)   satisfy demand at market j ;                            \n"
            "                                                                           \n"
            "  cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;                       \n"
            "                                                                           \n"
            "  supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;                               \n"
            "                                                                           \n"
            "  demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;                               \n"
            "                                                                           \n"
            "  Model transport /all/ ;                                                  \n"
            "                                                                           \n"
            "  Solve transport using lp minimizing z ;                                  \n"
            "                                                                           \n"
            "$if not set dbOut1 $abort 'no file name for out-database 1 file provided'  \n"
            "  execute_unload '%dbOut1%', x, z;                                         \n";
}
<|endoftext|>


<commit_before>/*
Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
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 Sony Pictures Imageworks nor the names of its
  contributors 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 <OpenColorIO/OpenColorIO.h>

OCIO_NAMESPACE_ENTER
{

    Exception::Exception(const char * msg) throw()
    : std::runtime_error(msg)
    {}

    Exception::Exception(const Exception& e) throw()
    : std::runtime_error(e)
    {}

    //*** ~Exception
    Exception::~Exception() throw()
    {
    }

    ExceptionMissingFile::ExceptionMissingFile(const char * msg) throw()
    : Exception(msg)
    {}

    ExceptionMissingFile::ExceptionMissingFile(const ExceptionMissingFile& e) throw()
    : Exception(e)
    {}

}
OCIO_NAMESPACE_EXIT

///////////////////////////////////////////////////////////////////////////////

#ifdef OCIO_UNIT_TEST

namespace OCIO = OCIO_NAMESPACE;
#include "UnitTest.h"

#include <string.h>

OIIO_ADD_TEST(Exception, Basic)
{
    static const char* dummyErrorStr = "Dummy error";

    // Test 1

    try
    {
        throw OCIO::Exception(dummyErrorStr);
    }
    catch(const std::exception& ex)
    {
        OIIO_CHECK_EQUAL(strcmp(ex.what(), dummyErrorStr), 0);
    }
    catch(...)
    {
        OIIO_CHECK_EQUAL(0x0, "wrong exception type");
    }

    // Test 2

    try
    {
        OCIO::Exception ex(dummyErrorStr);
        throw OCIO::Exception(ex);
    }
    catch(const std::exception& ex)
    {
        OIIO_CHECK_EQUAL(strcmp(ex.what(), dummyErrorStr), 0);
    }
    catch(...)
    {
        OIIO_CHECK_EQUAL(0x0, "wrong exception type");
    }
}

#endif // OCIO_UNIT_TEST
<commit_msg>Improve Exception test<commit_after>/*
Copyright (c) 2003-2010 Sony Pictures Imageworks Inc., et al.
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 Sony Pictures Imageworks nor the names of its
  contributors 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 <OpenColorIO/OpenColorIO.h>

OCIO_NAMESPACE_ENTER
{

    Exception::Exception(const char * msg) throw()
    : std::runtime_error(msg)
    {}

    Exception::Exception(const Exception& e) throw()
    : std::runtime_error(e)
    {}

    //*** ~Exception
    Exception::~Exception() throw()
    {
    }

    ExceptionMissingFile::ExceptionMissingFile(const char * msg) throw()
    : Exception(msg)
    {}

    ExceptionMissingFile::ExceptionMissingFile(const ExceptionMissingFile& e) throw()
    : Exception(e)
    {}

}
OCIO_NAMESPACE_EXIT

///////////////////////////////////////////////////////////////////////////////

#ifdef OCIO_UNIT_TEST

namespace OCIO = OCIO_NAMESPACE;
#include "UnitTest.h"

#include <string.h>

OIIO_ADD_TEST(Exception, Basic)
{
    static const char* dummyErrorStr = "Dummy error";

    // Test 1

    try
    {
        throw OCIO::Exception(dummyErrorStr);
    }
    catch(const std::exception& ex)
    {
        OIIO_CHECK_EQUAL(strcmp(ex.what(), dummyErrorStr), 0);
    }
    catch(...)
    {
        OIIO_CHECK_ASSERT(!"Wrong exception type");
    }

    // Test 2

    try
    {
        OCIO::Exception ex(dummyErrorStr);
        throw OCIO::Exception(ex);
    }
    catch(const std::exception& ex)
    {
        OIIO_CHECK_EQUAL(strcmp(ex.what(), dummyErrorStr), 0);
    }
    catch(...)
    {
        OIIO_CHECK_ASSERT(!"Wrong exception type");
    }
}

#endif // OCIO_UNIT_TEST
<|endoftext|>


<commit_before>/* =======================================================================
   Copyright (c) 2011, Institute for Microelectronics, TU Wien
   http://www.iue.tuwien.ac.at
                             -----------------
           ViennaFVM - The Vienna Finite Volume Method Library
                             -----------------

   authors:    Karl Rupp                          rupp@iue.tuwien.ac.at
               (add your name here)

   license:    To be discussed, see file LICENSE in the ViennaFVM base directory
======================================================================= */

#define VIENNAFVM_DEBUG

// include necessary system headers
#include <iostream>

// ViennaFVM includes:
#include "viennafvm/forwards.h"
#include "viennafvm/linear_assembler.hpp"
#include "viennafvm/io/vtk_writer.hpp"
#include "viennafvm/boundary.hpp"
#include "viennafvm/linear_solve.hpp"

// ViennaGrid includes:
#include "viennagrid/domain.hpp"
#include <viennagrid/config/simplex.hpp>
#include "viennagrid/io/netgen_reader.hpp"
#include "viennagrid/io/vtk_writer.hpp"
#include "viennagrid/algorithm/voronoi.hpp"

// ViennaData includes:
#include "viennadata/api.hpp"

// ViennaMath includes:
#include "viennamath/expression.hpp"

#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/operation.hpp>
#include <boost/numeric/ublas/operation_sparse.hpp>

int main()
{
  typedef double   numeric_type;

  typedef viennagrid::config::triangular_2d                           ConfigType;
  typedef viennagrid::result_of::domain<ConfigType>::type             DomainType;
  typedef typename ConfigType::cell_tag                     CellTag;

  typedef viennagrid::result_of::ncell<ConfigType, CellTag::dim>::type        CellType;
  typedef viennagrid::result_of::ncell_range<DomainType, CellTag::dim>::type  CellContainer;
  typedef viennagrid::result_of::iterator<CellContainer>::type                CellIterator;
  typedef viennagrid::result_of::ncell_range<CellType, 0>::type               VertexOnCellContainer;
  typedef viennagrid::result_of::iterator<VertexOnCellContainer>::type        VertexOnCellIterator;

  typedef boost::numeric::ublas::compressed_matrix<numeric_type>  MatrixType;
  typedef boost::numeric::ublas::vector<numeric_type>             VectorType;

  typedef viennamath::function_symbol   FunctionSymbol;
  typedef viennamath::equation          Equation;

  //
  // Create a domain from file
  //
  DomainType my_domain;

  try
  {
    viennagrid::io::netgen_reader my_reader;
    my_reader(my_domain, "../examples/data/square128.mesh");
  }
  catch (...)
  {
    std::cerr << "File-Reader failed. Aborting program..." << std::endl;
    return EXIT_FAILURE;
  }

  //
  // Specify two PDEs:
  //
  FunctionSymbol u(0, viennamath::unknown_tag<>());   //an unknown function used for PDE specification
  FunctionSymbol v(1, viennamath::unknown_tag<>());   //an unknown function used for PDE specification
  Equation poisson_equ_1 = viennamath::make_equation( viennamath::laplace(u), -1);
  Equation poisson_equ_2 = viennamath::make_equation( viennamath::laplace(v), 0);

  MatrixType system_matrix_1, system_matrix_2;
  VectorType load_vector_1, load_vector_2;

  //
  // Setting boundary information on domain (this should come from device specification)
  //
  //setting some boundary flags:
  CellContainer cells = viennagrid::ncells(my_domain);
  for (CellIterator cit  = cells.begin();
                    cit != cells.end();
                  ++cit)
  {
    VertexOnCellContainer vertices = viennagrid::ncells<0>(*cit);
    for (VertexOnCellIterator vit  = vertices.begin();
                              vit != vertices.end();
                            ++vit)
    {
      //boundary for first equation: Homogeneous Dirichlet everywhere
      if ( (*vit)[0] == 0.0 || (*vit)[0] == 1.0
           || (*vit)[1] == 0.0 || (*vit)[1] == 1.0 )
        viennafvm::set_dirichlet_boundary(*cit, 0.0, 0);  //simulation with ID 0 uses homogeneous boundary data

      //boundary for second equation (ID 1): 0 at left boundary, 1 at right boundary
      if ( (*vit)[0] == 0.0)
        viennafvm::set_dirichlet_boundary(*cit, 0.0, 1);
      else if ( (*vit)[0] == 1.0)
        viennafvm::set_dirichlet_boundary(*cit, 1.0, 1);
    }
  }

  //
  // Create PDE solver functors: (discussion about proper interface required)
  //
  viennafvm::linear_assembler fvm_assembler;

  //
  // Solve system and write solution vector to pde_result:
  // (discussion about proper interface required. Introduce a pde_result class?)
  //
  fvm_assembler(viennafvm::make_linear_pde_system(poisson_equ_1, u),
                my_domain,
                system_matrix_1,
                load_vector_1
              );

  VectorType pde_result_1 = viennafvm::solve(system_matrix_1, load_vector_1);
  viennafvm::io::write_solution_to_VTK_file(pde_result_1, "poisson_2d_1", my_domain, 0);

  fvm_assembler(viennafvm::make_linear_pde_system(poisson_equ_2, v, viennafvm::make_linear_pde_options(1, 1)),
                my_domain,
                system_matrix_2,
                load_vector_2
              );

  //std::cout << system_matrix_2 << std::endl;
  //std::cout << load_vector_2 << std::endl;

  VectorType pde_result_2 = viennafvm::solve(system_matrix_2, load_vector_2);

  //
  // Writing solution back to domain (discussion about proper way of returning a solution required...)
  //
  viennafvm::io::write_solution_to_VTK_file(pde_result_2, "poisson_2d_2", my_domain, 1);

  std::cout << "*****************************************" << std::endl;
  std::cout << "* Poisson solver finished successfully! *" << std::endl;
  std::cout << "*****************************************" << std::endl;
  return EXIT_SUCCESS;
}

<commit_msg>Fixed Poisson 2D example.<commit_after>/* =======================================================================
   Copyright (c) 2011, Institute for Microelectronics, TU Wien
   http://www.iue.tuwien.ac.at
                             -----------------
           ViennaFVM - The Vienna Finite Volume Method Library
                             -----------------

   authors:    Karl Rupp                          rupp@iue.tuwien.ac.at
               (add your name here)

   license:    To be discussed, see file LICENSE in the ViennaFVM base directory
======================================================================= */

#define VIENNAFVM_DEBUG

// include necessary system headers
#include <iostream>

// ViennaFVM includes:
#include "viennafvm/forwards.h"
#include "viennafvm/linear_assembler.hpp"
#include "viennafvm/io/vtk_writer.hpp"
#include "viennafvm/boundary.hpp"
#include "viennafvm/linear_solve.hpp"
#include "viennafvm/pde_solver.hpp"

// ViennaGrid includes:
#include "viennagrid/domain.hpp"
#include <viennagrid/config/simplex.hpp>
#include "viennagrid/io/netgen_reader.hpp"
#include "viennagrid/io/vtk_writer.hpp"
#include "viennagrid/algorithm/voronoi.hpp"

// ViennaData includes:
#include "viennadata/api.hpp"

// ViennaMath includes:
#include "viennamath/expression.hpp"

#include <boost/numeric/ublas/io.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/operation.hpp>
#include <boost/numeric/ublas/operation_sparse.hpp>

int main()
{
  typedef double   numeric_type;

  typedef viennagrid::config::triangular_2d                           ConfigType;
  typedef viennagrid::result_of::domain<ConfigType>::type             DomainType;
  typedef typename ConfigType::cell_tag                     CellTag;

  typedef viennagrid::result_of::ncell<ConfigType, CellTag::dim>::type        CellType;
  typedef viennagrid::result_of::ncell_range<DomainType, CellTag::dim>::type  CellContainer;
  typedef viennagrid::result_of::iterator<CellContainer>::type                CellIterator;
  typedef viennagrid::result_of::ncell_range<CellType, 0>::type               VertexOnCellContainer;
  typedef viennagrid::result_of::iterator<VertexOnCellContainer>::type        VertexOnCellIterator;

  typedef boost::numeric::ublas::compressed_matrix<numeric_type>  MatrixType;
  typedef boost::numeric::ublas::vector<numeric_type>             VectorType;

  typedef viennamath::function_symbol   FunctionSymbol;
  typedef viennamath::equation          Equation;

  //
  // Create a domain from file
  //
  DomainType my_domain;

  try
  {
    viennagrid::io::netgen_reader my_reader;
    my_reader(my_domain, "../examples/data/square128.mesh");
  }
  catch (...)
  {
    std::cerr << "File-Reader failed. Aborting program..." << std::endl;
    return EXIT_FAILURE;
  }

  //
  // Specify two PDEs:
  //
  FunctionSymbol u(0, viennamath::unknown_tag<>());   //an unknown function used for PDE specification
  FunctionSymbol v(1, viennamath::unknown_tag<>());   //an unknown function used for PDE specification
  Equation poisson_equ_1 = viennamath::make_equation( viennamath::laplace(u), -1);
  Equation poisson_equ_2 = viennamath::make_equation( viennamath::laplace(v), 0);

  MatrixType system_matrix_1, system_matrix_2;
  VectorType load_vector_1, load_vector_2;

  //
  // Setting boundary information on domain (this should come from device specification)
  //
  //setting some boundary flags:
  CellContainer cells = viennagrid::ncells(my_domain);
  for (CellIterator cit  = cells.begin();
                    cit != cells.end();
                  ++cit)
  {
    VertexOnCellContainer vertices = viennagrid::ncells<0>(*cit);
    for (VertexOnCellIterator vit  = vertices.begin();
                              vit != vertices.end();
                            ++vit)
    {
      //boundary for first equation: Homogeneous Dirichlet everywhere
      if ( (*vit)[0] == 0.0 || (*vit)[0] == 1.0
           || (*vit)[1] == 0.0 || (*vit)[1] == 1.0 )
        viennafvm::set_dirichlet_boundary(*cit, 0.0, 0);  //simulation with ID 0 uses homogeneous boundary data

      //boundary for second equation (ID 1): 0 at left boundary, 1 at right boundary
      if ( (*vit)[0] == 0.0)
        viennafvm::set_dirichlet_boundary(*cit, 0.0, 1);
      else if ( (*vit)[0] == 1.0)
        viennafvm::set_dirichlet_boundary(*cit, 1.0, 1);
    }
  }

  //
  // Create PDE solver instance
  //
  viennafvm::pde_solver<> pde_solver;

  //
  // Pass system to solver:
  //
  pde_solver(viennafvm::make_linear_pde_system(poisson_equ_1, u),  // PDE with associated unknown
             my_domain);

  viennafvm::io::write_solution_to_VTK_file(pde_solver.result(), "poisson_2d_1", my_domain, 0);

  pde_solver(viennafvm::make_linear_pde_system(poisson_equ_2, v, viennafvm::make_linear_pde_options(1, 1)),  // PDE with associated unknown
             my_domain);

  //
  // Writing solution back to domain (discussion about proper way of returning a solution required...)
  //
  viennafvm::io::write_solution_to_VTK_file(pde_solver.result(), "poisson_2d_2", my_domain, 1);

  std::cout << "*****************************************" << std::endl;
  std::cout << "* Poisson solver finished successfully! *" << std::endl;
  std::cout << "*****************************************" << std::endl;
  return EXIT_SUCCESS;
}

<|endoftext|>


<commit_before>//////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Achim Brandt
/// @author Dr. Frank Celler
/// @author Jan Christoph Uhde
////////////////////////////////////////////////////////////////////////////////

#include "GeneralCommTask.h"

#include "Basics/HybridLogicalClock.h"
#include "Basics/MutexLocker.h"
#include "Basics/StaticStrings.h"
#include "GeneralServer/AsyncJobManager.h"
#include "GeneralServer/GeneralServer.h"
#include "GeneralServer/GeneralServerFeature.h"
#include "GeneralServer/RestHandler.h"
#include "GeneralServer/RestHandlerFactory.h"
#include "Logger/Logger.h"
#include "Meta/conversion.h"
#include "Rest/VppResponse.h"
#include "Scheduler/Job.h"
#include "Scheduler/JobGuard.h"
#include "Scheduler/JobQueue.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/Socket.h"
#include "Scheduler/SchedulerFeature.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

GeneralCommTask::GeneralCommTask(EventLoop loop, GeneralServer* server,
                                 std::unique_ptr<Socket> socket,
                                 ConnectionInfo&& info, double keepAliveTimeout,
                                 bool skipSocketInit)
    : Task(loop, "GeneralCommTask"),
      SocketTask(loop, std::move(socket), std::move(info), keepAliveTimeout, skipSocketInit),
      _server(server) {}

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

void GeneralCommTask::executeRequest(
    std::unique_ptr<GeneralRequest>&& request,
    std::unique_ptr<GeneralResponse>&& response) {
  // check for an async request (before the handler steals the request)
  bool found = false;
  std::string const& asyncExecution =
      request->header(StaticStrings::Async, found);

  // store the message id for error handling
  uint64_t messageId = 0UL;
  if (request) {
    messageId = request->messageId();
  } else if (response) {
    messageId = response->messageId();
  } else {
    LOG_TOPIC(WARN, Logger::COMMUNICATION)
        << "could not find corresponding request/response";
  }

  // create a handler, this takes ownership of request and response
  std::shared_ptr<RestHandler> handler(
      GeneralServerFeature::HANDLER_FACTORY->createHandler(
          std::move(request), std::move(response)));

  // transfer statistics into handler
  getAgent(messageId)->transferTo(handler.get());

  if (handler == nullptr) {
    LOG(TRACE) << "no handler is known, giving up";
    handleSimpleError(rest::ResponseCode::NOT_FOUND, messageId);
    return;
  }

  // asynchronous request
  bool ok = false;

  if (found && (asyncExecution == "true" || asyncExecution == "store")) {
    // getAgent(messageId)->requestStatisticsAgentSetAsync();
    handler->requestStatisticsAgentSetAsync();
    uint64_t jobId = 0;

    if (asyncExecution == "store") {
      // persist the responses
      ok = handleRequestAsync(std::move(handler), &jobId);
    } else {
      // don't persist the responses
      ok = handleRequestAsync(std::move(handler));
    }

    if (ok) {
      std::unique_ptr<GeneralResponse> response =
          createResponse(rest::ResponseCode::ACCEPTED, messageId);

      if (jobId > 0) {
        // return the job id we just created
        response->setHeaderNC(StaticStrings::AsyncId, StringUtils::itoa(jobId));
      }

      processResponse(response.get());
      return;
    } else {
      handleSimpleError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_QUEUE_FULL,
                        TRI_errno_string(TRI_ERROR_QUEUE_FULL), messageId);
    }
  }

  // synchronous request
  else {
    ok = handleRequest(std::move(handler));
  }

  if (!ok) {
    handleSimpleError(rest::ResponseCode::SERVER_ERROR, messageId);
  }
}

void GeneralCommTask::processResponse(GeneralResponse* response) {
  if (response == nullptr) {
    LOG_TOPIC(WARN, Logger::COMMUNICATION)
        << "processResponse received a nullptr, closing connection";
    closeStream();
  } else {
    addResponse(response);
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

bool GeneralCommTask::handleRequest(std::shared_ptr<RestHandler> handler) {
  if (handler->isDirect()) {
    handleRequestDirectly(std::move(handler));
    return true;
  }

  if (_loop._scheduler->isIdle()) {
    handleRequestDirectly(std::move(handler));
    return true;
  }

  bool startThread = handler->needsOwnThread();

  if (startThread) {
    handleRequestDirectly(std::move(handler));
    return true;
  }

  // ok, we need to queue the request
  LOG_TOPIC(TRACE, Logger::THREADS) << "too much work, queuing handler";
  size_t queue = handler->queue();
  uint64_t messageId = handler->messageId();

  auto self = shared_from_this();
  std::unique_ptr<Job> job(
      new Job(_server, std::move(handler),
              [self, this](std::shared_ptr<RestHandler> h) {
                handleRequestDirectly(h);
              }));

  bool ok =
      SchedulerFeature::SCHEDULER->jobQueue()->queue(queue, std::move(job));

  if (!ok) {
    handleSimpleError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_QUEUE_FULL,
                      TRI_errno_string(TRI_ERROR_QUEUE_FULL), messageId);
  }

  return ok;
}

void GeneralCommTask::handleRequestDirectly(
    std::shared_ptr<RestHandler> handler) {
  JobGuard guard(_loop);
  guard.work();

  RequestStatisticsAgent* agent = getAgent(handler->messageId());

  auto self = shared_from_this();
  handler->initEngine(_loop, agent, [self, this](RestHandler* h) {
    h->transferTo(getAgent(h->messageId()));
    addResponse(h->response());
  });

  HandlerWorkStack monitor(handler);
  monitor->asyncRunEngine();
}

bool GeneralCommTask::handleRequestAsync(std::shared_ptr<RestHandler> handler,
                                         uint64_t* jobId) {
  // extract the coordinator flag
  bool found;
  std::string const& hdrStr =
      handler->request()->header(StaticStrings::Coordinator, found);
  char const* hdr = found ? hdrStr.c_str() : nullptr;

  // use the handler id as identifier
  bool store = false;

  if (jobId != nullptr) {
    store = true;
    *jobId = handler->handlerId();
    GeneralServerFeature::JOB_MANAGER->initAsyncJob(handler.get(), hdr);
  }

  if (store) {
    auto self = shared_from_this();
    handler->initEngine(_loop, nullptr, [this, self](RestHandler* handler) {
      handler->transferTo(getAgent(handler->messageId()));
      GeneralServerFeature::JOB_MANAGER->finishAsyncJob(handler);
    });
  } else {
    handler->initEngine(_loop, nullptr, [](RestHandler* handler) {});
  }

  // queue this job
  size_t queue = handler->queue();
  auto self = shared_from_this();

  std::unique_ptr<Job> job(
      new Job(_server, std::move(handler),
              [self, this](std::shared_ptr<RestHandler> h) {
                JobGuard guard(_loop);
                guard.work();

                h->asyncRunEngine();
              }));

  return SchedulerFeature::SCHEDULER->jobQueue()->queue(queue, std::move(job));
}
<commit_msg>use make_unique<commit_after>//////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2014-2016 ArangoDB GmbH, Cologne, Germany
/// Copyright 2004-2014 triAGENS GmbH, Cologne, Germany
///
/// 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.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Achim Brandt
/// @author Dr. Frank Celler
/// @author Jan Christoph Uhde
////////////////////////////////////////////////////////////////////////////////

#include "GeneralCommTask.h"

#include "Basics/HybridLogicalClock.h"
#include "Basics/MutexLocker.h"
#include "Basics/StaticStrings.h"
#include "GeneralServer/AsyncJobManager.h"
#include "GeneralServer/GeneralServer.h"
#include "GeneralServer/GeneralServerFeature.h"
#include "GeneralServer/RestHandler.h"
#include "GeneralServer/RestHandlerFactory.h"
#include "Logger/Logger.h"
#include "Meta/conversion.h"
#include "Rest/VppResponse.h"
#include "Scheduler/Job.h"
#include "Scheduler/JobGuard.h"
#include "Scheduler/JobQueue.h"
#include "Scheduler/Scheduler.h"
#include "Scheduler/Socket.h"
#include "Scheduler/SchedulerFeature.h"

using namespace arangodb;
using namespace arangodb::basics;
using namespace arangodb::rest;

// -----------------------------------------------------------------------------
// --SECTION--                                      constructors and destructors
// -----------------------------------------------------------------------------

GeneralCommTask::GeneralCommTask(EventLoop loop, GeneralServer* server,
                                 std::unique_ptr<Socket> socket,
                                 ConnectionInfo&& info, double keepAliveTimeout,
                                 bool skipSocketInit)
    : Task(loop, "GeneralCommTask"),
      SocketTask(loop, std::move(socket), std::move(info), keepAliveTimeout, skipSocketInit),
      _server(server) {}

// -----------------------------------------------------------------------------
// --SECTION--                                                 protected methods
// -----------------------------------------------------------------------------

void GeneralCommTask::executeRequest(
    std::unique_ptr<GeneralRequest>&& request,
    std::unique_ptr<GeneralResponse>&& response) {
  // check for an async request (before the handler steals the request)
  bool found = false;
  std::string const& asyncExecution =
      request->header(StaticStrings::Async, found);

  // store the message id for error handling
  uint64_t messageId = 0UL;
  if (request) {
    messageId = request->messageId();
  } else if (response) {
    messageId = response->messageId();
  } else {
    LOG_TOPIC(WARN, Logger::COMMUNICATION)
        << "could not find corresponding request/response";
  }

  // create a handler, this takes ownership of request and response
  std::shared_ptr<RestHandler> handler(
      GeneralServerFeature::HANDLER_FACTORY->createHandler(
          std::move(request), std::move(response)));

  // transfer statistics into handler
  getAgent(messageId)->transferTo(handler.get());

  if (handler == nullptr) {
    LOG(TRACE) << "no handler is known, giving up";
    handleSimpleError(rest::ResponseCode::NOT_FOUND, messageId);
    return;
  }

  // asynchronous request
  bool ok = false;

  if (found && (asyncExecution == "true" || asyncExecution == "store")) {
    // getAgent(messageId)->requestStatisticsAgentSetAsync();
    handler->requestStatisticsAgentSetAsync();
    uint64_t jobId = 0;

    if (asyncExecution == "store") {
      // persist the responses
      ok = handleRequestAsync(std::move(handler), &jobId);
    } else {
      // don't persist the responses
      ok = handleRequestAsync(std::move(handler));
    }

    if (ok) {
      std::unique_ptr<GeneralResponse> response =
          createResponse(rest::ResponseCode::ACCEPTED, messageId);

      if (jobId > 0) {
        // return the job id we just created
        response->setHeaderNC(StaticStrings::AsyncId, StringUtils::itoa(jobId));
      }

      processResponse(response.get());
      return;
    } else {
      handleSimpleError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_QUEUE_FULL,
                        TRI_errno_string(TRI_ERROR_QUEUE_FULL), messageId);
    }
  }

  // synchronous request
  else {
    ok = handleRequest(std::move(handler));
  }

  if (!ok) {
    handleSimpleError(rest::ResponseCode::SERVER_ERROR, messageId);
  }
}

void GeneralCommTask::processResponse(GeneralResponse* response) {
  if (response == nullptr) {
    LOG_TOPIC(WARN, Logger::COMMUNICATION)
        << "processResponse received a nullptr, closing connection";
    closeStream();
  } else {
    addResponse(response);
  }
}

// -----------------------------------------------------------------------------
// --SECTION--                                                   private methods
// -----------------------------------------------------------------------------

bool GeneralCommTask::handleRequest(std::shared_ptr<RestHandler> handler) {
  if (handler->isDirect()) {
    handleRequestDirectly(std::move(handler));
    return true;
  }

  if (_loop._scheduler->isIdle()) {
    handleRequestDirectly(std::move(handler));
    return true;
  }

  bool startThread = handler->needsOwnThread();

  if (startThread) {
    handleRequestDirectly(std::move(handler));
    return true;
  }

  // ok, we need to queue the request
  LOG_TOPIC(TRACE, Logger::THREADS) << "too much work, queuing handler";
  size_t queue = handler->queue();
  uint64_t messageId = handler->messageId();

  auto self = shared_from_this();
  std::unique_ptr<Job> job(
      new Job(_server, std::move(handler),
              [self, this](std::shared_ptr<RestHandler> h) {
                handleRequestDirectly(h);
              }));

  bool ok =
      SchedulerFeature::SCHEDULER->jobQueue()->queue(queue, std::move(job));

  if (!ok) {
    handleSimpleError(rest::ResponseCode::SERVER_ERROR, TRI_ERROR_QUEUE_FULL,
                      TRI_errno_string(TRI_ERROR_QUEUE_FULL), messageId);
  }

  return ok;
}

void GeneralCommTask::handleRequestDirectly(
    std::shared_ptr<RestHandler> handler) {
  JobGuard guard(_loop);
  guard.work();

  RequestStatisticsAgent* agent = getAgent(handler->messageId());

  auto self = shared_from_this();
  handler->initEngine(_loop, agent, [self, this](RestHandler* h) {
    h->transferTo(getAgent(h->messageId()));
    addResponse(h->response());
  });

  HandlerWorkStack monitor(handler);
  monitor->asyncRunEngine();
}

bool GeneralCommTask::handleRequestAsync(std::shared_ptr<RestHandler> handler,
                                         uint64_t* jobId) {
  // extract the coordinator flag
  bool found;
  std::string const& hdrStr =
      handler->request()->header(StaticStrings::Coordinator, found);
  char const* hdr = found ? hdrStr.c_str() : nullptr;

  // use the handler id as identifier
  bool store = false;

  if (jobId != nullptr) {
    store = true;
    *jobId = handler->handlerId();
    GeneralServerFeature::JOB_MANAGER->initAsyncJob(handler.get(), hdr);
  }

  if (store) {
    auto self = shared_from_this();
    handler->initEngine(_loop, nullptr, [this, self](RestHandler* handler) {
      handler->transferTo(getAgent(handler->messageId()));
      GeneralServerFeature::JOB_MANAGER->finishAsyncJob(handler);
    });
  } else {
    handler->initEngine(_loop, nullptr, [](RestHandler* handler) {});
  }

  // queue this job
  size_t queue = handler->queue();
  auto self = shared_from_this();

  auto job = std::make_unique<Job>(_server, std::move(handler),
              [self, this](std::shared_ptr<RestHandler> h) {
                JobGuard guard(_loop);
                guard.work();

                h->asyncRunEngine();
              });

  return SchedulerFeature::SCHEDULER->jobQueue()->queue(queue, std::move(job));
}
<|endoftext|>


<commit_before>//===- Printer.cpp - Code for printing data structure graphs nicely -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the 'dot' graph printer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
#include "llvm/Analysis/DataStructure/DSGraphTraits.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
#include <sstream>
using namespace llvm;

// OnlyPrintMain - The DataStructure printer exposes this option to allow
// printing of only the graph for "main".
//
namespace {
  cl::opt<bool> OnlyPrintMain("only-print-main-ds", cl::ReallyHidden);
  cl::opt<bool> DontPrintAnything("dont-print-ds", cl::ReallyHidden);
  Statistic<> MaxGraphSize   ("dsa", "Maximum graph size");
  Statistic<> NumFoldedNodes ("dsa", "Number of folded nodes (in final graph)");
}

void DSNode::dump() const { print(std::cerr, 0); }

static std::string getCaption(const DSNode *N, const DSGraph *G) {
  std::stringstream OS;
  Module *M = 0;

  if (!G) G = N->getParentGraph();

  // Get the module from ONE of the functions in the graph it is available.
  if (G && !G->getReturnNodes().empty())
    M = G->getReturnNodes().begin()->first->getParent();
  if (M == 0 && G) {
    // If there is a global in the graph, we can use it to find the module.
    const DSScalarMap &SM = G->getScalarMap();
    if (SM.global_begin() != SM.global_end())
      M = (*SM.global_begin())->getParent();
  }

  if (N->isNodeCompletelyFolded())
    OS << "COLLAPSED";
  else {
    WriteTypeSymbolic(OS, N->getType(), M);
    if (N->isArray())
      OS << " array";
  }
  if (unsigned NodeType = N->getNodeFlags()) {
    OS << ": ";
    if (NodeType & DSNode::AllocaNode ) OS << "S";
    if (NodeType & DSNode::HeapNode   ) OS << "H";
    if (NodeType & DSNode::GlobalNode ) OS << "G";
    if (NodeType & DSNode::UnknownNode) OS << "U";
    if (NodeType & DSNode::Incomplete ) OS << "I";
    if (NodeType & DSNode::Modified   ) OS << "M";
    if (NodeType & DSNode::Read       ) OS << "R";
#ifndef NDEBUG
    if (NodeType & DSNode::DEAD       ) OS << "<dead>";
#endif
    OS << "\n";
  }

  for (unsigned i = 0, e = N->getGlobals().size(); i != e; ++i) {
    WriteAsOperand(OS, N->getGlobals()[i], false, true, M);
    OS << "\n";
  }

  return OS.str();
}

namespace llvm {
template<>
struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
  static std::string getGraphName(const DSGraph *G) {
    switch (G->getReturnNodes().size()) {
    case 0: return G->getFunctionNames();
    case 1: return "Function " + G->getFunctionNames();
    default: return "Functions: " + G->getFunctionNames();
    }
  }

  static std::string getNodeLabel(const DSNode *Node, const DSGraph *Graph) {
    return getCaption(Node, Graph);
  }

  static std::string getNodeAttributes(const DSNode *N) {
    return "shape=Mrecord";
  }

  static bool edgeTargetsEdgeSource(const void *Node,
                                    DSNode::const_iterator I) {
    unsigned O = I.getNode()->getLink(I.getOffset()).getOffset();
    return (O >> DS::PointerShift) != 0;
  }

  static DSNode::const_iterator getEdgeTarget(const DSNode *Node,
                                              DSNode::const_iterator I) {
    unsigned O = I.getNode()->getLink(I.getOffset()).getOffset();
    unsigned LinkNo = O >> DS::PointerShift;
    const DSNode *N = *I;
    DSNode::const_iterator R = N->begin();
    for (; LinkNo; --LinkNo)
      ++R;
    return R;
  }

  /// addCustomGraphFeatures - Use this graph writing hook to emit call nodes
  /// and the return node.
  ///
  static void addCustomGraphFeatures(const DSGraph *G,
                                     GraphWriter<const DSGraph*> &GW) {
    Module *CurMod = 0;
    if (!G->getReturnNodes().empty())
      CurMod = G->getReturnNodes().begin()->first->getParent();
    else {
      // If there is a global in the graph, we can use it to find the module.
      const DSScalarMap &SM = G->getScalarMap();
      if (SM.global_begin() != SM.global_end())
        CurMod = (*SM.global_begin())->getParent();
    }

    // Add scalar nodes to the graph...
    const DSGraph::ScalarMapTy &VM = G->getScalarMap();
    for (DSGraph::ScalarMapTy::const_iterator I = VM.begin(); I != VM.end();++I)
      if (!isa<GlobalValue>(I->first)) {
        std::stringstream OS;
        WriteAsOperand(OS, I->first, false, true, CurMod);
        GW.emitSimpleNode(I->first, "", OS.str());

        // Add edge from return node to real destination
        int EdgeDest = I->second.getOffset() >> DS::PointerShift;
        if (EdgeDest == 0) EdgeDest = -1;
        GW.emitEdge(I->first, -1, I->second.getNode(),
                    EdgeDest, "arrowtail=tee,color=gray63");
      }

    // Output the returned value pointer...
    const DSGraph::ReturnNodesTy &RetNodes = G->getReturnNodes();
    for (DSGraph::ReturnNodesTy::const_iterator I = RetNodes.begin(),
           E = RetNodes.end(); I != E; ++I)
      if (I->second.getNode()) {
        std::string Label;
        if (RetNodes.size() == 1)
          Label = "returning";
        else
          Label = I->first->getName() + " ret node";
        // Output the return node...
        GW.emitSimpleNode((void*)I->first, "plaintext=circle", Label);

        // Add edge from return node to real destination
        int RetEdgeDest = I->second.getOffset() >> DS::PointerShift;;
        if (RetEdgeDest == 0) RetEdgeDest = -1;
        GW.emitEdge((void*)I->first, -1, I->second.getNode(),
                    RetEdgeDest, "arrowtail=tee,color=gray63");
      }

    // Output all of the call nodes...
    const std::vector<DSCallSite> &FCs =
      G->shouldPrintAuxCalls() ? G->getAuxFunctionCalls()
      : G->getFunctionCalls();
    for (unsigned i = 0, e = FCs.size(); i != e; ++i) {
      const DSCallSite &Call = FCs[i];
      std::vector<std::string> EdgeSourceCaptions(Call.getNumPtrArgs()+2);
      EdgeSourceCaptions[0] = "r";
      if (Call.isDirectCall())
        EdgeSourceCaptions[1] = Call.getCalleeFunc()->getName();
      else
        EdgeSourceCaptions[1] = "f";

      GW.emitSimpleNode(&Call, "shape=record", "call", Call.getNumPtrArgs()+2,
                        &EdgeSourceCaptions);

      if (DSNode *N = Call.getRetVal().getNode()) {
        int EdgeDest = Call.getRetVal().getOffset() >> DS::PointerShift;
        if (EdgeDest == 0) EdgeDest = -1;
        GW.emitEdge(&Call, 0, N, EdgeDest, "color=gray63,tailclip=false");
      }

      // Print out the callee...
      if (Call.isIndirectCall()) {
        DSNode *N = Call.getCalleeNode();
        assert(N && "Null call site callee node!");
        GW.emitEdge(&Call, 1, N, -1, "color=gray63,tailclip=false");
      }

      for (unsigned j = 0, e = Call.getNumPtrArgs(); j != e; ++j)
        if (DSNode *N = Call.getPtrArg(j).getNode()) {
          int EdgeDest = Call.getPtrArg(j).getOffset() >> DS::PointerShift;
          if (EdgeDest == 0) EdgeDest = -1;
          GW.emitEdge(&Call, j+2, N, EdgeDest, "color=gray63,tailclip=false");
        }
    }
  }
};
}   // end namespace llvm

void DSNode::print(std::ostream &O, const DSGraph *G) const {
  GraphWriter<const DSGraph *> W(O, G);
  W.writeNode(this);
}

void DSGraph::print(std::ostream &O) const {
  WriteGraph(O, this, "DataStructures");
}

void DSGraph::writeGraphToFile(std::ostream &O,
                               const std::string &GraphName) const {
  std::string Filename = GraphName + ".dot";
  O << "Writing '" << Filename << "'...";
  std::ofstream F(Filename.c_str());

  if (F.good()) {
    print(F);
    unsigned NumCalls = shouldPrintAuxCalls() ?
      getAuxFunctionCalls().size() : getFunctionCalls().size();
    O << " [" << getGraphSize() << "+" << NumCalls << "]\n";
  } else {
    O << "  error opening file for writing!\n";
  }
}

/// viewGraph - Emit a dot graph, run 'dot', run gv on the postscript file,
/// then cleanup.  For use from the debugger.
///
void DSGraph::viewGraph() const {
  std::ofstream F("/tmp/tempgraph.dot");
  if (!F.good()) {
    std::cerr << "Error opening '/tmp/tempgraph.dot' for temporary graph!\n";
    return;
  }
  print(F);
  F.close();
  if (system("dot -Tps -Gsize=10,7.5 -Grotate=90 /tmp/tempgraph.dot > /tmp/tempgraph.ps"))
    std::cerr << "Error running dot: 'dot' not in path?\n";
  system("gv /tmp/tempgraph.ps");
  system("rm /tmp/tempgraph.dot /tmp/tempgraph.ps");
}

template <typename Collection>
static void printCollection(const Collection &C, std::ostream &O,
                            const Module *M, const std::string &Prefix) {
  if (M == 0) {
    O << "Null Module pointer, cannot continue!\n";
    return;
  }

  unsigned TotalNumNodes = 0, TotalCallNodes = 0;
  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (C.hasGraph(*I)) {
      DSGraph &Gr = C.getDSGraph((Function&)*I);
      TotalNumNodes += Gr.getGraphSize();
      unsigned NumCalls = Gr.shouldPrintAuxCalls() ?
        Gr.getAuxFunctionCalls().size() : Gr.getFunctionCalls().size();

      TotalCallNodes += NumCalls;
      if (I->getName() == "main" || !OnlyPrintMain)
        Gr.writeGraphToFile(O, Prefix+I->getName());
      else {
        O << "Skipped Writing '" << Prefix+I->getName() << ".dot'... ["
          << Gr.getGraphSize() << "+" << NumCalls << "]\n";
      }

      unsigned GraphSize = Gr.getGraphSize();
      if (MaxGraphSize < GraphSize) MaxGraphSize = GraphSize;

      for (DSGraph::node_iterator NI = Gr.node_begin(), E = Gr.node_end();
           NI != E; ++NI)
        if ((*NI)->isNodeCompletelyFolded())
          ++NumFoldedNodes;
    }

  DSGraph &GG = C.getGlobalsGraph();
  TotalNumNodes  += GG.getGraphSize();
  TotalCallNodes += GG.getFunctionCalls().size();
  if (!OnlyPrintMain) {
    GG.writeGraphToFile(O, Prefix+"GlobalsGraph");
  } else {
    O << "Skipped Writing '" << Prefix << "GlobalsGraph.dot'... ["
      << GG.getGraphSize() << "+" << GG.getFunctionCalls().size() << "]\n";
  }

  O << "\nGraphs contain [" << TotalNumNodes << "+" << TotalCallNodes
    << "] nodes total" << std::endl;
}

// print - Print out the analysis results...
void LocalDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "ds.");
}

void BUDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "bu.");
}

void TDDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "td.");
}

void CompleteBUDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "cbu.");
}

<commit_msg>Fix some more problems where we called getOffset before getNode()<commit_after>//===- Printer.cpp - Code for printing data structure graphs nicely -------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the 'dot' graph printer.
//
//===----------------------------------------------------------------------===//

#include "llvm/Analysis/DataStructure/DataStructure.h"
#include "llvm/Analysis/DataStructure/DSGraph.h"
#include "llvm/Analysis/DataStructure/DSGraphTraits.h"
#include "llvm/Module.h"
#include "llvm/Constants.h"
#include "llvm/Assembly/Writer.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/ADT/Statistic.h"
#include <fstream>
#include <sstream>
using namespace llvm;

// OnlyPrintMain - The DataStructure printer exposes this option to allow
// printing of only the graph for "main".
//
namespace {
  cl::opt<bool> OnlyPrintMain("only-print-main-ds", cl::ReallyHidden);
  cl::opt<bool> DontPrintAnything("dont-print-ds", cl::ReallyHidden);
  Statistic<> MaxGraphSize   ("dsa", "Maximum graph size");
  Statistic<> NumFoldedNodes ("dsa", "Number of folded nodes (in final graph)");
}

void DSNode::dump() const { print(std::cerr, 0); }

static std::string getCaption(const DSNode *N, const DSGraph *G) {
  std::stringstream OS;
  Module *M = 0;

  if (!G) G = N->getParentGraph();

  // Get the module from ONE of the functions in the graph it is available.
  if (G && !G->getReturnNodes().empty())
    M = G->getReturnNodes().begin()->first->getParent();
  if (M == 0 && G) {
    // If there is a global in the graph, we can use it to find the module.
    const DSScalarMap &SM = G->getScalarMap();
    if (SM.global_begin() != SM.global_end())
      M = (*SM.global_begin())->getParent();
  }

  if (N->isNodeCompletelyFolded())
    OS << "COLLAPSED";
  else {
    WriteTypeSymbolic(OS, N->getType(), M);
    if (N->isArray())
      OS << " array";
  }
  if (unsigned NodeType = N->getNodeFlags()) {
    OS << ": ";
    if (NodeType & DSNode::AllocaNode ) OS << "S";
    if (NodeType & DSNode::HeapNode   ) OS << "H";
    if (NodeType & DSNode::GlobalNode ) OS << "G";
    if (NodeType & DSNode::UnknownNode) OS << "U";
    if (NodeType & DSNode::Incomplete ) OS << "I";
    if (NodeType & DSNode::Modified   ) OS << "M";
    if (NodeType & DSNode::Read       ) OS << "R";
#ifndef NDEBUG
    if (NodeType & DSNode::DEAD       ) OS << "<dead>";
#endif
    OS << "\n";
  }

  for (unsigned i = 0, e = N->getGlobals().size(); i != e; ++i) {
    WriteAsOperand(OS, N->getGlobals()[i], false, true, M);
    OS << "\n";
  }

  return OS.str();
}

namespace llvm {
template<>
struct DOTGraphTraits<const DSGraph*> : public DefaultDOTGraphTraits {
  static std::string getGraphName(const DSGraph *G) {
    switch (G->getReturnNodes().size()) {
    case 0: return G->getFunctionNames();
    case 1: return "Function " + G->getFunctionNames();
    default: return "Functions: " + G->getFunctionNames();
    }
  }

  static std::string getNodeLabel(const DSNode *Node, const DSGraph *Graph) {
    return getCaption(Node, Graph);
  }

  static std::string getNodeAttributes(const DSNode *N) {
    return "shape=Mrecord";
  }

  static bool edgeTargetsEdgeSource(const void *Node,
                                    DSNode::const_iterator I) {
    unsigned O = I.getNode()->getLink(I.getOffset()).getOffset();
    return (O >> DS::PointerShift) != 0;
  }

  static DSNode::const_iterator getEdgeTarget(const DSNode *Node,
                                              DSNode::const_iterator I) {
    unsigned O = I.getNode()->getLink(I.getOffset()).getOffset();
    unsigned LinkNo = O >> DS::PointerShift;
    const DSNode *N = *I;
    DSNode::const_iterator R = N->begin();
    for (; LinkNo; --LinkNo)
      ++R;
    return R;
  }

  /// addCustomGraphFeatures - Use this graph writing hook to emit call nodes
  /// and the return node.
  ///
  static void addCustomGraphFeatures(const DSGraph *G,
                                     GraphWriter<const DSGraph*> &GW) {
    Module *CurMod = 0;
    if (!G->getReturnNodes().empty())
      CurMod = G->getReturnNodes().begin()->first->getParent();
    else {
      // If there is a global in the graph, we can use it to find the module.
      const DSScalarMap &SM = G->getScalarMap();
      if (SM.global_begin() != SM.global_end())
        CurMod = (*SM.global_begin())->getParent();
    }

    // Add scalar nodes to the graph...
    const DSGraph::ScalarMapTy &VM = G->getScalarMap();
    for (DSGraph::ScalarMapTy::const_iterator I = VM.begin(); I != VM.end();++I)
      if (!isa<GlobalValue>(I->first)) {
        std::stringstream OS;
        WriteAsOperand(OS, I->first, false, true, CurMod);
        GW.emitSimpleNode(I->first, "", OS.str());

        // Add edge from return node to real destination
        DSNode *DestNode = I->second.getNode();
        int EdgeDest = I->second.getOffset() >> DS::PointerShift;
        if (EdgeDest == 0) EdgeDest = -1;
        GW.emitEdge(I->first, -1, DestNode,
                    EdgeDest, "arrowtail=tee,color=gray63");
      }

    // Output the returned value pointer...
    const DSGraph::ReturnNodesTy &RetNodes = G->getReturnNodes();
    for (DSGraph::ReturnNodesTy::const_iterator I = RetNodes.begin(),
           E = RetNodes.end(); I != E; ++I)
      if (I->second.getNode()) {
        std::string Label;
        if (RetNodes.size() == 1)
          Label = "returning";
        else
          Label = I->first->getName() + " ret node";
        // Output the return node...
        GW.emitSimpleNode((void*)I->first, "plaintext=circle", Label);

        // Add edge from return node to real destination
        DSNode *RetNode = I->second.getNode();
        int RetEdgeDest = I->second.getOffset() >> DS::PointerShift;;
        if (RetEdgeDest == 0) RetEdgeDest = -1;
        GW.emitEdge((void*)I->first, -1, RetNode,
                    RetEdgeDest, "arrowtail=tee,color=gray63");
      }

    // Output all of the call nodes...
    const std::vector<DSCallSite> &FCs =
      G->shouldPrintAuxCalls() ? G->getAuxFunctionCalls()
      : G->getFunctionCalls();
    for (unsigned i = 0, e = FCs.size(); i != e; ++i) {
      const DSCallSite &Call = FCs[i];
      std::vector<std::string> EdgeSourceCaptions(Call.getNumPtrArgs()+2);
      EdgeSourceCaptions[0] = "r";
      if (Call.isDirectCall())
        EdgeSourceCaptions[1] = Call.getCalleeFunc()->getName();
      else
        EdgeSourceCaptions[1] = "f";

      GW.emitSimpleNode(&Call, "shape=record", "call", Call.getNumPtrArgs()+2,
                        &EdgeSourceCaptions);

      if (DSNode *N = Call.getRetVal().getNode()) {
        int EdgeDest = Call.getRetVal().getOffset() >> DS::PointerShift;
        if (EdgeDest == 0) EdgeDest = -1;
        GW.emitEdge(&Call, 0, N, EdgeDest, "color=gray63,tailclip=false");
      }

      // Print out the callee...
      if (Call.isIndirectCall()) {
        DSNode *N = Call.getCalleeNode();
        assert(N && "Null call site callee node!");
        GW.emitEdge(&Call, 1, N, -1, "color=gray63,tailclip=false");
      }

      for (unsigned j = 0, e = Call.getNumPtrArgs(); j != e; ++j)
        if (DSNode *N = Call.getPtrArg(j).getNode()) {
          int EdgeDest = Call.getPtrArg(j).getOffset() >> DS::PointerShift;
          if (EdgeDest == 0) EdgeDest = -1;
          GW.emitEdge(&Call, j+2, N, EdgeDest, "color=gray63,tailclip=false");
        }
    }
  }
};
}   // end namespace llvm

void DSNode::print(std::ostream &O, const DSGraph *G) const {
  GraphWriter<const DSGraph *> W(O, G);
  W.writeNode(this);
}

void DSGraph::print(std::ostream &O) const {
  WriteGraph(O, this, "DataStructures");
}

void DSGraph::writeGraphToFile(std::ostream &O,
                               const std::string &GraphName) const {
  std::string Filename = GraphName + ".dot";
  O << "Writing '" << Filename << "'...";
  std::ofstream F(Filename.c_str());

  if (F.good()) {
    print(F);
    unsigned NumCalls = shouldPrintAuxCalls() ?
      getAuxFunctionCalls().size() : getFunctionCalls().size();
    O << " [" << getGraphSize() << "+" << NumCalls << "]\n";
  } else {
    O << "  error opening file for writing!\n";
  }
}

/// viewGraph - Emit a dot graph, run 'dot', run gv on the postscript file,
/// then cleanup.  For use from the debugger.
///
void DSGraph::viewGraph() const {
  std::ofstream F("/tmp/tempgraph.dot");
  if (!F.good()) {
    std::cerr << "Error opening '/tmp/tempgraph.dot' for temporary graph!\n";
    return;
  }
  print(F);
  F.close();
  if (system("dot -Tps -Gsize=10,7.5 -Grotate=90 /tmp/tempgraph.dot > /tmp/tempgraph.ps"))
    std::cerr << "Error running dot: 'dot' not in path?\n";
  system("gv /tmp/tempgraph.ps");
  system("rm /tmp/tempgraph.dot /tmp/tempgraph.ps");
}

template <typename Collection>
static void printCollection(const Collection &C, std::ostream &O,
                            const Module *M, const std::string &Prefix) {
  if (M == 0) {
    O << "Null Module pointer, cannot continue!\n";
    return;
  }

  unsigned TotalNumNodes = 0, TotalCallNodes = 0;
  for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
    if (C.hasGraph(*I)) {
      DSGraph &Gr = C.getDSGraph((Function&)*I);
      TotalNumNodes += Gr.getGraphSize();
      unsigned NumCalls = Gr.shouldPrintAuxCalls() ?
        Gr.getAuxFunctionCalls().size() : Gr.getFunctionCalls().size();

      TotalCallNodes += NumCalls;
      if (I->getName() == "main" || !OnlyPrintMain)
        Gr.writeGraphToFile(O, Prefix+I->getName());
      else {
        O << "Skipped Writing '" << Prefix+I->getName() << ".dot'... ["
          << Gr.getGraphSize() << "+" << NumCalls << "]\n";
      }

      unsigned GraphSize = Gr.getGraphSize();
      if (MaxGraphSize < GraphSize) MaxGraphSize = GraphSize;

      for (DSGraph::node_iterator NI = Gr.node_begin(), E = Gr.node_end();
           NI != E; ++NI)
        if ((*NI)->isNodeCompletelyFolded())
          ++NumFoldedNodes;
    }

  DSGraph &GG = C.getGlobalsGraph();
  TotalNumNodes  += GG.getGraphSize();
  TotalCallNodes += GG.getFunctionCalls().size();
  if (!OnlyPrintMain) {
    GG.writeGraphToFile(O, Prefix+"GlobalsGraph");
  } else {
    O << "Skipped Writing '" << Prefix << "GlobalsGraph.dot'... ["
      << GG.getGraphSize() << "+" << GG.getFunctionCalls().size() << "]\n";
  }

  O << "\nGraphs contain [" << TotalNumNodes << "+" << TotalCallNodes
    << "] nodes total" << std::endl;
}

// print - Print out the analysis results...
void LocalDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "ds.");
}

void BUDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "bu.");
}

void TDDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "td.");
}

void CompleteBUDataStructures::print(std::ostream &O, const Module *M) const {
  if (DontPrintAnything) return;
  printCollection(*this, O, M, "cbu.");
}

<|endoftext|>