铛链接器重复符号问题

时间:2019-02-25 10:48:16

标签: c++ makefile linker duplicate-symbol

当我遇到以下问题时,我正在尝试为我的论文项目编译一些代码:clang链接器不断告诉我一些符号已在不同的目标文件中重复;查看其他有类似问题的用户,这看起来像是Xcode问题(我在2012年中期在Macbook Pro上运行,macOS High Sierra),但是我一直使用clang遵循类似的规则进行编译,但从未发现类似的问题错误。

这些是我的密码;我将包括标题,源代码和makefile ev_mpi.hpp

#ifndef RANK_RNG_OFFSET
#define RANK_RNG_OFFSET 1000
#endif

#include <mpi.h>

namespace ev_mpi {

bool MPI_Is_initialized (void)
{
  int is_parallel;
  MPI_Initialized( &is_parallel );
  return (bool)is_parallel;
}

template<class data_type> MPI_Datatype MPI_Data_convert(void);
template<> MPI_Datatype MPI_Data_convert<char>(void)                { return MPI_CHAR; }
template<> MPI_Datatype MPI_Data_convert<short int>(void)           { return MPI_SHORT; }
template<> MPI_Datatype MPI_Data_convert<int>(void)                 { return MPI_INT; }
template<> MPI_Datatype MPI_Data_convert<long int>(void)            { return MPI_LONG; }
template<> MPI_Datatype MPI_Data_convert<unsigned char>(void)       { return MPI_UNSIGNED_CHAR; }
template<> MPI_Datatype MPI_Data_convert<unsigned short int>(void)  { return MPI_UNSIGNED_SHORT; }
template<> MPI_Datatype MPI_Data_convert<unsigned int>(void)        { return MPI_UNSIGNED; }
template<> MPI_Datatype MPI_Data_convert<unsigned long int>(void)   { return MPI_UNSIGNED_LONG; }
template<> MPI_Datatype MPI_Data_convert<float>(void)               { return MPI_FLOAT; }
template<> MPI_Datatype MPI_Data_convert<double>(void)              { return MPI_DOUBLE; }
template<> MPI_Datatype MPI_Data_convert<long double>(void)         { return MPI_LONG_DOUBLE; }

int MPI_Get_rank(MPI_Comm comm = MPI_COMM_WORLD)
{
  int rank;
  MPI_Comm_rank(comm, &rank);
  return rank;
}

int MPI_Get_size(MPI_Comm comm = MPI_COMM_WORLD)
{
  int size;
  MPI_Comm_size(comm, &size);
  return size;
}

int MPI_Seed_rank (int seed)
{
  if ( MPI_Is_initialized() )
    return seed + RANK_RNG_OFFSET*MPI_Get_rank();
  else
    return seed;
}

}

#endif /* EV_MPI_HPP */

ev_constants.hpp

#ifndef EV_CONSTANTS_HPP
#define EV_CONSTANTS_HPP

#ifndef real_number
#define real_number double
#endif

namespace ev_const {

  constexpr double  pi      = 3.141592653589793238462643383279502884197;
  constexpr double  pio2    = 1.57079632679489661923132169163975144209858;
  constexpr double  pi2     = 6.283185307179586476925286766559005768394;
  constexpr double  sqrt2   = 1.41421356237309504880168872420969807856967;
  constexpr double  euler   = 0.5772156649015328606065120900824024310422;
  constexpr float   pi_s    = 3.141592653589793238462643383279502884197;
  constexpr float   pio2_s  = 1.57079632679489661923132169163975144209858;
  constexpr float   pi2_s   = 6.283185307179586476925286766559005768394;

}

#endif /* EV_CONSTANTS_HPP */

ev_utilities.hpp

#ifndef EV_UTILITIES
#define EV_UTILITIES

#include "ev_constants.hpp"
#include "ev_mpi.hpp"

#include <Eigen/Dense>
#include <iostream>
#include <cassert>
#include <algorithm>

#ifndef MPI_DEFAULT_TAG
#define MPI_DEFAULT_TAG 0
#endif

namespace ev_utility {

inline int power_n(int x, unsigned int n)
{
  if (n == 0)
    return 1;
  else if (n%2 == 0)
    return power_n(x, n/2)*power_n(x, n/2);
  else
    return x*power_n(x, n/2)*power_n(x, n/2);
}

template<unsigned N> struct power_impl {
  template<typename T>
  static T calc(const T &x) {
    if (N%2 == 0)
      return power_impl<N/2>::calc(x*x);
    else if (N%3 == 0)
      return power_impl<N/3>::calc(x*x*x);
    return power_impl<N-1>::calc(x)*x;
  }
};
template<> struct power_impl<0> {
  template<typename T>
  static T calc(const T &) {
    return 1;
  }
};
template<unsigned N, typename T>
inline T power(const T &x) {
  return power_impl<N>::calc(x);
}


template <class data_type, int StorageOrder = Eigen::RowMajor>
class MaskMatrix {
protected:
  typedef typename Eigen::Matrix<data_type, Eigen::Dynamic, Eigen::Dynamic, StorageOrder> DynamicMatrix;
  int low_x, up_x, low_y, up_y;
  int dim_x, dim_y;
  DynamicMatrix data;
public:
  MaskMatrix ( int lx, int ux, int ly, int uy ):
    low_x(lx), up_x(ux), low_y(ly), up_y(uy), dim_x(ux-lx), dim_y(uy-ly), data(dim_x, dim_y)
  { }
  MaskMatrix ( int lx, int ux, int ly, int uy, const data_type& dfl ):
    MaskMatrix(lx,ux,ly,uy) { data.fill(dfl); }
  MaskMatrix ( int lx, int ux, int ly, int uy, const DynamicMatrix& rhs ):
    low_x(lx), up_x(ux), low_y(ly), up_y(uy), dim_x(ux-lx), dim_y(uy-ly), data(rhs)
  { }
  MaskMatrix ( int l, int u ): MaskMatrix(l, u, l, u) { }
  MaskMatrix ( int l, int u, const data_type& dfl ): MaskMatrix(l, u, l, u, dfl) { }
  MaskMatrix ( int l, int u, const DynamicMatrix& rhs ): MaskMatrix(l, u, l, u, rhs) { }
  MaskMatrix& operator = (const MaskMatrix& rhs)
  {
    if ( rhs.dim_x != dim_x || rhs.dim_y != dim_y )
      std::cerr << "Matrix dimensions do not agree" << std::endl;
    else
      data = rhs.data;
    return *this;
  }
  void swap ( MaskMatrix& rhs )
  {
    if ( rhs.dim_x != dim_x || rhs.dim_y != dim_y )
      std::cerr << "Matrix dimensions do not agree" << std::endl;
    else
      data.swap(rhs.data);
  }
  inline int idx_i(const int& i) const
  {
    return i - low_x;
  }
  inline int idx_j(const int& j) const
  {
    return j - low_y;
  }
  void send_block
  (int block_i, int block_j, int block_x, int block_y, int recv_rank,
    int tag = MPI_DEFAULT_TAG, MPI_Comm comm = MPI_COMM_WORLD)
  {
    assert( ev_mpi::MPI_Is_initialized() );
    DynamicMatrix data_block = data.block(idx_i(block_i), idx_j(block_j), block_x, block_y);
    MPI_Send(data_block.data(), block_x*block_y, ev_mpi::MPI_Data_convert<data_type>(), recv_rank, tag, comm);
  }
  void recv_block
  (int block_i, int block_j, int block_x, int block_y, int send_rank,
    int tag = MPI_DEFAULT_TAG, MPI_Comm comm = MPI_COMM_WORLD, MPI_Status* stat = MPI_STATUS_IGNORE)
  {
    assert( ev_mpi::MPI_Is_initialized() );
    DynamicMatrix data_block(block_x, block_y);
    MPI_Recv(data_block.data(), block_x*block_y, ev_mpi::MPI_Data_convert<data_type>(), send_rank, tag, comm, stat);
    data.block(idx_i(block_i), idx_j(block_j), block_x, block_y) = data_block;
  }
  ~MaskMatrix()
  { }
  data_type& operator () (int i, int j)
  {
    return data( idx_i(i), idx_j(j) );
  }
  const data_type& operator () (int i, int j) const
  {
    return data( idx_i(i), idx_j(j) );
  }
  void transpose ( void )
  {
    data.transposeInPlace();
    int temp;
    temp = low_x;   low_x = low_y;    low_y = temp;
    temp = low_x;   low_y = low_x;    low_x = temp;
    temp = up_x;    up_x = up_y;      up_y = temp;
    temp = up_y;    up_y = up_x;      up_x = temp;
    temp = dim_x;   dim_x = dim_y;    dim_y = temp;
  }
  MaskMatrix submatrix ( int lx, int ux, int ly, int uy )
  {
    MaskMatrix sub( lx, ux, ly, uy, data.block(idx_i(lx), idx_j(ly-low_y), ux-lx, uy-ly) );
    return sub;
  }
};


template <class data_type, int StorageOrder = Eigen::RowMajor>
class MaskMatrixMPI : public MaskMatrix<data_type, StorageOrder>
{
protected:
  typedef MaskMatrix<data_type,StorageOrder> Base;
  typedef typename Base::DynamicMatrix DynamicMatrix;
  const MaskMatrix<int>& rank_schema;
  int n_cut;
  int ux_recv[8], lx_recv[8];
  int uy_recv[8], ly_recv[8];
  int ux_send[8], lx_send[8];
  int uy_send[8], ly_send[8];
  int rank_exc[8];
  void inline set_schema()
  {
    rank_exc[0] = rank_schema(Base::low_x, Base::low_y);
    rank_exc[1] = rank_schema(Base::low_x+n_cut, Base::low_y);
    rank_exc[2] = rank_schema(Base::up_x-n_cut, Base::low_y);
    rank_exc[3] = rank_schema(Base::up_x-n_cut, Base::low_y+n_cut);
    rank_exc[4] = rank_schema(Base::up_x-n_cut, Base::up_y-n_cut);
    rank_exc[5] = rank_schema(Base::low_x+n_cut, Base::up_y-n_cut);
    rank_exc[6] = rank_schema(Base::low_x, Base::up_y-n_cut);
    rank_exc[7] = rank_schema(Base::low_x, Base::low_y+n_cut);
    lx_recv[0] = Base::low_x;           ly_recv[0] = Base::low_y;
    ux_recv[0] = Base::low_x+n_cut;     uy_recv[0] = Base::low_y+n_cut;
    lx_recv[1] = Base::low_x+n_cut;     ly_recv[1] = Base::low_y;
    ux_recv[1] = Base::up_x-n_cut;      uy_recv[1] = Base::low_y+n_cut;
    lx_recv[2] = Base::up_x-n_cut;      ly_recv[2] = Base::low_y;
    ux_recv[2] = Base::up_x;            uy_recv[2] = Base::low_y+n_cut;
    lx_recv[3] = Base::up_x-n_cut;      ly_recv[3] = Base::low_y+n_cut;
    ux_recv[3] = Base::up_x;            uy_recv[3] = Base::up_y-n_cut;
    lx_recv[4] = Base::up_x-n_cut;      ly_recv[4] = Base::up_y-n_cut;
    ux_recv[4] = Base::up_x;            uy_recv[4] = Base::up_y;
    lx_recv[5] = Base::low_x+n_cut;     ly_recv[5] = Base::up_y-n_cut;
    ux_recv[5] = Base::up_x-n_cut;      uy_recv[5] = Base::up_y;
    lx_recv[6] = Base::low_x;           ly_recv[6] = Base::up_y-n_cut;
    ux_recv[6] = Base::low_x+n_cut;     uy_recv[6] = Base::up_y;
    lx_recv[7] = Base::low_x;           ly_recv[7] = Base::low_y+n_cut;
    ux_recv[7] = Base::low_x+n_cut;     uy_recv[7] = Base::up_y-n_cut;
    lx_send[0] = Base::low_x+n_cut;     ly_send[0] = Base::low_y+n_cut;
    ux_send[0] = Base::low_x+2*n_cut;   uy_send[0] = Base::low_y+2*n_cut;
    lx_send[1] = Base::low_x+n_cut;     ly_send[1] = Base::low_y+n_cut;
    ux_send[1] = Base::up_x-n_cut;      uy_send[1] = Base::low_y+2*n_cut;
    lx_send[2] = Base::up_x-2*n_cut;    ly_send[2] = Base::low_y+n_cut;
    ux_send[2] = Base::up_x-n_cut;      uy_send[2] = Base::low_y+2*n_cut;
    lx_send[3] = Base::up_x-2*n_cut;    ly_send[3] = Base::low_y+n_cut;
    ux_send[3] = Base::up_x-n_cut;      uy_send[3] = Base::up_y-n_cut;
    lx_send[4] = Base::up_x-2*n_cut;    ly_send[4] = Base::up_y-2*n_cut;
    ux_send[4] = Base::up_x-n_cut;      uy_send[4] = Base::up_y-n_cut;
    lx_send[5] = Base::low_x+n_cut;     ly_send[5] = Base::up_y-2*n_cut;
    ux_send[5] = Base::up_x-n_cut;      uy_send[5] = Base::up_y-n_cut;
    lx_send[6] = Base::low_x+n_cut;     ly_send[6] = Base::up_y-2*n_cut;
    ux_send[6] = Base::low_x+2*n_cut;   uy_send[6] = Base::up_y-n_cut;
    lx_send[7] = Base::low_x+n_cut;     ly_send[7] = Base::low_y+n_cut;
    ux_send[7] = Base::low_x+2*n_cut;   uy_send[7] = Base::up_y-n_cut;
  }
public:
  MaskMatrixMPI( const MaskMatrix<data_type>& data_, const MaskMatrix<int>& rs, int nc ):
    MaskMatrix<data_type>(data_), rank_schema(rs), n_cut(nc) { set_schema(); }
  void send_block
  ( int idx, int tag = MPI_DEFAULT_TAG, MPI_Comm comm = MPI_COMM_WORLD )
  {
    assert(rank_exc[idx] != -1);
    Base::send_block(lx_send[idx], ly_send[idx], ux_send[idx]-lx_send[idx], uy_send[idx]-ly_send[idx], rank_exc[idx], tag, comm);
  }
  void recv_block
  ( int idx, int tag = MPI_DEFAULT_TAG, MPI_Comm comm = MPI_COMM_WORLD, MPI_Status* stat = MPI_STATUS_IGNORE )
  {
    assert(rank_exc[idx] != -1);
    Base::recv_block(lx_recv[idx], ly_recv[idx], ux_recv[idx]-lx_recv[idx], uy_recv[idx]-ly_recv[idx], rank_exc[idx], tag, comm, stat);
  }
  inline int idx_from_rank(const int& r) const
  {
    auto it = std::find(rank_exc, rank_exc+8, r);
    if ( it == rank_exc+8 )
      return -1;
    else
      return (int)(it-rank_exc);
  }
  inline int rank_from_idx(const int& i) const
  {
    return rank_exc[i];
  }
  inline void print_rank_exc(void) const
  {
    for (int i = 0; i<8; ++i)
      std::cout << rank_exc[i] << " ";
    std::cout << std::endl;
  }
};

}

#endif /* EV_UTILITIES */

ev_numeric.hpp

#ifndef EV_NUMERIC_HPP
#define EV_NUMERIC_HPP

#include "ev_utilities.hpp"

#include <functional>
#include <vector>
#include <iterator>
#include <cmath>
#include <iostream>
#include <limits>

namespace ev_numeric
{

std::vector<real_number> spline (std::vector<real_number>::const_iterator, std::vector<real_number>::const_iterator,
  int, real_number, real_number);

real_number splint (std::vector<real_number>::const_iterator, std::vector<real_number>::const_iterator,
  std::vector<real_number>::const_iterator, int, real_number);

class
Polint
{

private:
  std::vector<real_number>::const_iterator xa_begin;
  std::vector<real_number>::const_iterator xa_end;
  std::vector<real_number>::const_iterator ya_begin;
  std::vector<real_number>::const_iterator ya_end;
  real_number x;
  int n, ns;
  real_number den, dif, dift, ho, hp, w;
  std::vector<real_number> c, d;
  void polint_init(void);

public:
  Polint() = default;
  Polint(std::vector<real_number>::const_iterator, std::vector<real_number>::const_iterator,
    std::vector<real_number>::const_iterator, std::vector<real_number>::const_iterator, real_number);
  // Interpolate over given vector
  void interpolate(real_number&, real_number&);
  // Interpolate over new vector
  void interpolate(std::vector<real_number>::const_iterator, std::vector<real_number>::const_iterator,
    std::vector<real_number>::const_iterator, std::vector<real_number>::const_iterator,
    real_number, real_number&, real_number&);

};


class
RombergIntegrator {

private:

  int JMAX = 14, K = 5;
  int JMAXP = JMAX+1, KM = K-1;
  real_number EPS = 1.0e-9;

  std::function<real_number(real_number)> func;                               
  std::function<real_number(real_number)> funk = [this](real_number x) {      
    return func(1.0/x)/(x*x);
  };
  real_number a, b;      // extremes (finite)
  real_number aa, bb;    // extreme (infinite)

  Polint interpolator;

  void integration_step(const std::function<real_number(real_number)>&, const real_number&, const real_number&,
    const int&, real_number&) const;
  void mid_point (const int&, real_number&) const;
  void mid_point_inf (const int&, real_number&) const;

public:

  enum integral_type {finite, infinite};

  RombergIntegrator() = default;
  RombergIntegrator(int JMAX_, int K_, real_number EPS_):
    JMAX(JMAX_), K(K_), JMAXP(JMAX_+1), KM(K_-1), EPS(EPS_), interpolator() { }
  RombergIntegrator(std::function<real_number(real_number)> func_, real_number a_, real_number b_):
    func(func_), a(a_), b(b_), aa(1.0/b_), bb(1.0/a_), interpolator() { }
  RombergIntegrator(int JMAX_, int K_, real_number EPS_,
    std::function<real_number(real_number)> func_, real_number a_, real_number b_ )
  {
    RombergIntegrator(JMAX_, K_, EPS_);
    RombergIntegrator(func_, a_, b_);
  }

  real_number integrate(integral_type);
  real_number integrate(std::function<real_number(real_number)>, real_number, real_number, integral_type);

  inline void set_jmax(int new_jmax) { JMAX = new_jmax; JMAXP = JMAX+1; }
  inline void set_k(int new_k) { K = new_k; KM = K-1; }
  inline void set_eps(real_number new_eps) { EPS = new_eps; }

  inline int get_jmax(void) const { return JMAX; }
  inline int get_k(void) const { return K; }
  inline real_number get_eps(void) const { return EPS; }

  ~RombergIntegrator() = default;

};


}

#endif /* EV_NUMERIC_HPP */

ev_numeric.cpp

#include "ev_numeric.hpp"

std::vector<real_number>
ev_numeric::spline
(std::vector<real_number>::const_iterator x, std::vector<real_number>::const_iterator y,
  int n, real_number yp1, real_number ypn)
{
  std::vector<real_number> y2(n), u(n);
  real_number sig, p, qn, un;
  if (yp1 > .99e30) {
    y2[0] = 0.0;
    u[0] = 0.0;
  }
  else {
    y2[0] = -0.5;
    u[0] = ( 3.0 / (x[1]-x[0]))*((y[1]-y[0] ) / ( x[1]-x[0])-yp1 );
  }
  for (int i = 1; i<n-1; ++i) {
    sig = ( x[i]-x[i-1]) / (x[i+1]-x[i-1] );
    p = sig * y2[i-1] + 2.0;
    y2[i] = (sig-1.0) / p;
    u[i] = (6.0*((y[i+1]-y[i])/(x[i+1]-x[i])-(y[i]-y[i-1])
      /(x[i]-x[i-1]))/(x[i+1]-x[i-1])-sig*u[i-1])/p;
  }
  if (ypn > .99e30) {
    qn = 0.0;
    un = 0.0;
  }
  else {
    qn = 0.5;
    un = (3.0/(x[n-1]-x[n-2]))*(ypn-(y[n-1]-y[n-2])/(x[n-1]-x[n-2]));
  }
  y2[n-1]=(un-qn*u[n-2])/(qn*y2[n-2]+1.0);
  for (int k = n-2; k>=0; --k) {
    y2[k]=y2[k]*y2[k+1]+u[k];
  }
  return y2;
}

real_number
ev_numeric::splint (std::vector<real_number>::const_iterator xa, std::vector<real_number>::const_iterator ya,
  std::vector<real_number>::const_iterator y2a, int n, real_number x)
{
  int klo = 1, khi = n, k;
  while (khi-klo > 1) {
    k = (khi+klo)/2;
    if (xa[k-1] > x) {
       khi = k;
    }
    else {
       klo = k;
    }
  }
  real_number h = xa[khi-1] - xa[klo-1];
  if ( h == 0.0 )
    std::cerr << "Bad xa input in splint" << std::endl;
  real_number a = (xa[khi-1]-x) / h;
  real_number b = (x-xa[klo-1]) / h;
  return a*ya[klo-1]+b*ya[khi-1]+((a*a*a-a)*y2a[klo-1]+(b*b*b-b)*y2a[khi-1])*(h*h) / 6.0;
}

ev_numeric::Polint::Polint
(std::vector<real_number>::const_iterator xa_begin_, std::vector<real_number>::const_iterator xa_end_,
  std::vector<real_number>::const_iterator ya_begin_, std::vector<real_number>::const_iterator ya_end_, real_number x_):
  xa_begin(xa_begin_), xa_end(xa_end_), ya_begin(ya_begin_), ya_end(ya_end_),
  x(x_), dif(abs(x-xa_begin_[0])), c(ya_begin_, ya_end_), d(ya_begin_, ya_end_),
  n(std::distance(xa_begin, xa_end))
{
  polint_init();
}

void
ev_numeric::Polint::polint_init
(void)
{
  ns = 1;
  for (int i = 0; i<n; ++i) {
    dift = abs(x-xa_begin[i]);
    if (dift <= dif) {
       ns = i;
       dif = dift;
    }
  }
}

void
ev_numeric::Polint::interpolate
(real_number& y, real_number& dy)
{
  y = ya_begin[ns];
  ns = ns-1;
  for (int m = 0; m<n-1; ++m) {
    for (int i = 0; i<n-m; ++i) {
      ho = xa_begin[i] - x;
      hp = xa_begin[i+m] - x;
      w = c[i+1] - d[i];
      den = ho - hp;
      if ( den == 0.0 )
      {
        std::cerr << "Failure in polint" << std::endl;
        return;
      }
      den = w/den;
      d[i] = hp*den;
      c[i] = ho*den;
    }
    if ( 2*ns <= n-m )
      dy = c[ns+1];
    else
    {
      dy = d[ns];
      ns = ns-1;
    }
    y = y + dy;
  }
  dif = abs(x-xa_begin[0]);
  c.assign(ya_begin, ya_end);
  d.assign(ya_begin, ya_end);
  polint_init();
}

void
ev_numeric::Polint::interpolate
(std::vector<real_number>::const_iterator xa_begin_new, std::vector<real_number>::const_iterator xa_end_new,
  std::vector<real_number>::const_iterator ya_begin_new, std::vector<real_number>::const_iterator ya_end_new,
  real_number x_new, real_number& y, real_number& dy)
{
  xa_begin = xa_begin_new; xa_end = xa_end_new; ya_begin = ya_begin_new; ya_end = ya_end_new; x = x_new;
  dif = abs(x-xa_begin[0]);
  c.assign(ya_begin, ya_end);
  d.assign(ya_begin, ya_end);
  n = std::distance(xa_begin, xa_end);
  polint_init();
  interpolate(y, dy);
}

void
ev_numeric::RombergIntegrator::integration_step
(const std::function<real_number(real_number)>& FUNC,
  const real_number& A, const real_number& B, const int& n, real_number& s) const
{
  int it;
  real_number del, ddel, sum, x;
  if (n==1)
    s = (B-A) * func( 0.5*(A+B) );
  else {
    it = ev_utility::power_n(3, n-2);
    del = (B-A) / (3.0*it);
    ddel = 2*del;
    x = A + 0.5*del;
    sum = 0.0;
    for (int j = 0; j<it; ++j) {
      sum +=  FUNC(x);
      x += ddel;
      sum += FUNC(x);
      x += del;
    }
    s = ( s+(B-A)*sum/it )/3.0;
  }
}

void
ev_numeric::RombergIntegrator::mid_point
(const int& n, real_number& s) const
{
  integration_step(func, a, b, n, s);
}

void
ev_numeric::RombergIntegrator::mid_point_inf
(const int& n, real_number& s) const
{
  integration_step(funk, aa, bb, n, s);
}

real_number
ev_numeric::RombergIntegrator::integrate
(integral_type type)
{
  real_number dss, ss;
  std::vector<real_number> h(JMAXP, 0.0), s(JMAXP, 0.0);
  h[0]=1.0;
  for( int j=0; j<JMAX; ++j ) {
    switch (type) {
      case finite:
        mid_point(j+1, s[j]);
        break;
      case infinite:
        mid_point_inf(j+1, s[j]);
        break;
      default:
        std::cerr << "failure in qromo (unrecognized type of integral)" << std::endl;
        break;
    }
    if(j >= KM) {
      interpolator.interpolate(h.cbegin()+(j-KM), h.cend()-(JMAXP-j), s.cbegin()+(j-KM), s.cend()-(JMAXP-j),
        0.0, ss, dss);
      if (abs(dss) <= EPS*abs(ss))
        return ss;
    }
    s[j+1] = s[j];
    h[j+1] = h[j]/9.0;
  }
  std::cerr << "Too many steps in qromo" << std::endl;
  return ss;
}

real_number
ev_numeric::RombergIntegrator::integrate
(std::function<real_number(real_number)> FUNC, real_number A, real_number B, integral_type type)
{
  func = FUNC;
  a = A;  bb = 1/A;
  b = B;  aa = 1/B;
  return integrate(type);
}

main.cpp(虚拟)

#include "ev_numeric.hpp"

int main() {

  return 0;

}

Makefile:

CXX = mpicxx

STANDARD = -std=c++11
WARNINGS = -Wall
OPTIMIZATION = -g
CXXFLAGS = $(WARNINGS) $(STANDARD) $(OPTIMIZATION)
CPPFLAGS = -I/usr/local/Cellar/eigen/3.3.7/include/eigen3

EXEC = main

SRC = ev_numeric.cpp $(EXEC).cpp
HEADS = ev_mpi.hpp ev_constants.hpp ev_utilities.hpp ev_numeric.hpp
OBJS = ev_numeric.o $(EXEC).o

.DEFAULT_GOAL = all

ev_numeric.o $(EXEC).o: ev_mpi.hpp
ev_numeric.o $(EXEC).o: ev_constants.hpp
ev_numeric.o $(EXEC).o: ev_numeric.hpp
ev_numeric.o $(EXEC).o: ev_utilities.hpp

.PHONY: all clean distclean

all: $(EXEC)

$(EXEC): $(OBJS)
    $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(OPTIMIZATION) $^ -o $@

$(OBJS): $(SRC) $(HEADS)

clean:
    $(RM) $(EXEC)

distclean:
    $(RM) $(EXEC)
    $(RM) *.o

我收到以下错误:

MacBook-Pro-4:enskog_vlasov_cpp macbookpro$ make
mpicxx -Wall -std=c++11 -g -I/usr/local/Cellar/eigen/3.3.7/include/eigen3  -c -o ev_numeric.o ev_numeric.cpp
ev_numeric.cpp:72:59: warning: field 'd' will be initialized after field 'n' [-Wreorder]
  x(x_), dif(abs(x-xa_begin_[0])), c(ya_begin_, ya_end_), d(ya_begin_, ya_end_),
                                                          ^
1 warning generated.
mpicxx -Wall -std=c++11 -g -I/usr/local/Cellar/eigen/3.3.7/include/eigen3  -c -o main.o main.cpp
mpicxx -I/usr/local/Cellar/eigen/3.3.7/include/eigen3 -Wall -std=c++11 -g -g ev_numeric.o main.o -o main
duplicate symbol __ZN6ev_mpi16MPI_Data_convertItEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIsEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertImEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIlEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIjEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIiEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIhEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIfEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIeEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIdEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi16MPI_Data_convertIcEEP15ompi_datatype_tv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi18MPI_Is_initializedEv in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi12MPI_Get_rankEP19ompi_communicator_t in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi12MPI_Get_sizeEP19ompi_communicator_t in:
    ev_numeric.o
    main.o
duplicate symbol __ZN6ev_mpi13MPI_Seed_rankEi in:
    ev_numeric.o
    main.o
ld: 15 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [main] Error 1

现在,我不明白的是,这个问题是否与如何编写ev_mpi.hpp中的函数的声明Makefile有关。 有人可以帮忙吗?

0 个答案:

没有答案