Commit 1c23c841 by Francois Gygi

updated for serial version


git-svn-id: http://qboxcode.org/svn/qb/trunk@747 cba15fb0-1239-40c8-b417-11db7ca47a34
parent 8ff95e51
......@@ -15,7 +15,7 @@
// Context.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: Context.C,v 1.17 2008-09-08 15:56:18 fgygi Exp $
// $Id: Context.C,v 1.18 2009-11-30 02:33:49 fgygi Exp $
#include "Context.h"
#include <iostream>
......@@ -92,11 +92,11 @@ void Cdgsum2d(int icontxt, char* scope, char* top,
void Cdgamx2d(int icontxt, char scope[], char top[],int m,int n,double *A,
int lda, int *ra, int *ca, int rcflag, int rdest, int cdest)
{ return; }
{ if ( rcflag > 0 ) { *ca = 0; *ra = 0; } return; }
void Cdgamn2d(int icontxt, char scope[], char top[],int m,int n,double *A,
int lda, int *ra, int *ca, int rcflag, int rdest, int cdest)
{ return; }
{ if ( rcflag > 0 ) { *ca = 0; *ra = 0; } return; }
void Cdgebs2d(int icontxt, char scope[], char top[],int m,int n,double *A,
int lda)
......@@ -118,11 +118,11 @@ void Cigsum2d(int icontxt, char* scope, char* top,
void Cigamx2d(int icontxt, char scope[], char top[],int m,int n,int *A,int lda,
int *ra, int *ca, int rcflag, int rdest, int cdest)
{ return; }
{ if ( rcflag > 0 ) { *ca = 0; *ra = 0; } return; }
void Cigamn2d(int icontxt, char scope[], char top[],int m,int n,int *A,int lda,
int *ra, int *ca, int rcflag, int rdest, int cdest)
{ return; }
{ if ( rcflag > 0 ) { *ca = 0; *ra = 0; } return; }
void Cigebs2d(int icontxt, char scope[], char top[],int m,int n,int *A,
int lda)
......
......@@ -15,7 +15,7 @@
// Matrix.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: Matrix.C,v 1.20 2009-09-08 05:37:41 fgygi Exp $
// $Id: Matrix.C,v 1.21 2009-11-30 02:32:59 fgygi Exp $
#include <cassert>
#include <iostream>
......@@ -2395,8 +2395,8 @@ void DoubleMatrix::syevx(char uplo, valarray<double>& w, DoubleMatrix& z,
{
assert(m_==n_);
char jobz = 'V';
char range = 'A';
#ifdef SCALAPACK
char range = 'A';
int ione=1;
int lwork=-1;
double tmpwork;
......@@ -2673,6 +2673,20 @@ void ComplexMatrix::heevd(char uplo, valarray<double>& w, ComplexMatrix& z)
rwork, &lrwork, iwork, &liwork, &info);
//MPI_Bcast(&w[0], m_, MPI_DOUBLE, 0, ctxt_.comm());
if ( info != 0 )
{
cout << " Matrix::heevd requires lwork>=" << work[0] << endl;
cout << " Matrix::heevd, lwork>=" << lwork << endl;
cout << " Matrix::heevd, liwork>=" << liwork << endl;
cout << " Matrix::heevd, info=" << info<< endl;
#ifdef USE_MPI
MPI_Abort(MPI_COMM_WORLD, 2);
#else
exit(2);
#endif
delete[] work;
delete[] rwork;
delete[] iwork;
#else
// request optimal lwork size
int lwork=-1;
......@@ -2689,22 +2703,20 @@ void ComplexMatrix::heevd(char uplo, valarray<double>& w, ComplexMatrix& z)
z=*this;
zheev(&jobz, &uplo, &m_, z.val, &m_, &w[0], work, &lwork,
rwork, &info);
#endif
if ( info != 0 )
{
cout << " Matrix::heevd requires lwork>=" << work[0] << endl;
cout << " Matrix::heevd, lwork>=" << lwork << endl;
cout << " Matrix::heevd, liwork>=" << liwork << endl;
cout << " Matrix::heevd, info=" << info<< endl;
#ifdef USE_MPI
MPI_Abort(MPI_COMM_WORLD, 2);
#else
exit(2);
#endif
#endif
}
delete[] work;
delete[] rwork;
delete[] iwork;
}
}
......@@ -2811,6 +2823,22 @@ void ComplexMatrix::heevd(char uplo, valarray<double>& w)
rwork, &lrwork, iwork, &liwork, &info);
MPI_Bcast(&w[0], m_, MPI_DOUBLE, 0, ctxt_.comm());
if ( info != 0 )
{
cout << " Matrix::heevd requires lwork>=" << work[0] << endl;
cout << " Matrix::heevd, lwork>=" << lwork << endl;
cout << " Matrix::heevd, lrwork>=" << lrwork << endl;
cout << " Matrix::heevd, liwork>=" << liwork << endl;
cout << " Matrix::heevd, info=" << info << endl;
#ifdef USE_MPI
MPI_Abort(MPI_COMM_WORLD, 2);
#else
exit(2);
#endif
}
delete[] work;
delete[] rwork;
delete[] iwork;
#else
// request optimal lwork size
int lwork=-1;
......@@ -2833,7 +2861,6 @@ void ComplexMatrix::heevd(char uplo, valarray<double>& w)
cout << " Matrix::heevd requires lwork>=" << work[0] << endl;
cout << " Matrix::heevd, lwork>=" << lwork << endl;
cout << " Matrix::heevd, lrwork>=" << lrwork << endl;
cout << " Matrix::heevd, liwork>=" << liwork << endl;
cout << " Matrix::heevd, info=" << info << endl;
#ifdef USE_MPI
MPI_Abort(MPI_COMM_WORLD, 2);
......@@ -2843,7 +2870,6 @@ void ComplexMatrix::heevd(char uplo, valarray<double>& w)
}
delete[] work;
delete[] rwork;
delete[] iwork;
}
}
......
......@@ -15,7 +15,7 @@
// NonLocalPotential.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: NonLocalPotential.C,v 1.27 2008-09-08 15:56:18 fgygi Exp $
// $Id: NonLocalPotential.C,v 1.28 2009-11-30 02:32:13 fgygi Exp $
#include "NonLocalPotential.h"
#include "Species.h"
......@@ -1141,6 +1141,7 @@ double NonLocalPotential::energy(bool compute_hpsi, SlaterDet& dsd,
tmap["fnl_zemm"].stop();
}
#if USE_MPI
tmap["fnl_allreduce"].start();
// Allreduce fnl partial sum
MPI_Comm basis_comm = basis_.context().comm();
......@@ -1154,6 +1155,11 @@ double NonLocalPotential::energy(bool compute_hpsi, SlaterDet& dsd,
fnl_loc = 2.0 * fnl_buf;
else
fnl_loc = fnl_buf;
#else
// factor 2.0 in next line is: counting G, -G
if ( basis_.real() )
fnl_loc *= 2.0;
#endif
// accumulate Enl contribution
const int nbase = ctxt_.mycol() * sd_.c().nb();
......
......@@ -15,7 +15,7 @@
// SampleWriter.C:
//
////////////////////////////////////////////////////////////////////////////////
// $Id: SampleWriter.C,v 1.10 2008-09-08 16:26:36 fgygi Exp $
// $Id: SampleWriter.C,v 1.11 2009-11-30 02:31:15 fgygi Exp $
#include "SampleWriter.h"
......@@ -82,11 +82,11 @@ void SampleWriter::writeSample(const Sample& s, const string filename,
}
else
{
#if USE_MPI
MPI_File fh;
MPI_Info info;
MPI_Info_create(&info);
MPI_Offset fsize;
SharedFilePtr sfp(ctxt_.comm(),fh);
int err;
err = MPI_File_open(ctxt_.comm(),(char*) filename_cstr,
......@@ -98,6 +98,10 @@ void SampleWriter::writeSample(const Sample& s, const string filename,
ctxt_.barrier();
MPI_Status status;
#else
ofstream fh(filename_cstr);
#endif
SharedFilePtr sfp(ctxt_.comm(),fh);
if ( ctxt_.onpe0() )
{
string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
......@@ -120,12 +124,16 @@ void SampleWriter::writeSample(const Sample& s, const string filename,
ss << s.atoms;
header += ss.str();
int len = header.size();
#if USE_MPI
err = MPI_File_write_at(sfp.file(),sfp.mpi_offset(),(void*)header.c_str(),
len,MPI_CHAR,&status);
if ( err != 0 )
cout << ctxt_.mype() << ": error in MPI_File_write: header "
<< err << endl;
sfp.advance(len);
#else
fh.write(header.c_str(),len);
#endif
}
sfp.sync();
......@@ -142,21 +150,29 @@ void SampleWriter::writeSample(const Sample& s, const string filename,
{
char *trailer = "</fpmd:sample>\n";
int len = strlen(trailer);
#if USE_MPI
err = MPI_File_write_at(sfp.file(),sfp.mpi_offset(),(void*)trailer,
len,MPI_CHAR,&status);
if ( err != 0 )
cout << ctxt_.mype() << ": error in MPI_File_write: trailer "
<< err << endl;
sfp.advance(len);
#else
fh.write(trailer,len);
#endif
}
sfp.sync();
file_size = sfp.offset();
#if USE_MPI
err = MPI_File_close(&fh);
if ( err != 0 )
cout << ctxt_.mype() << ": error in MPI_File_close: " << err << endl;
#else
fh.close();
#endif
}
tm.stop();
......
......@@ -15,12 +15,20 @@
// SharedFilePtr.h
//
////////////////////////////////////////////////////////////////////////////////
// $Id: SharedFilePtr.h,v 1.3 2008-09-08 15:56:19 fgygi Exp $
// $Id: SharedFilePtr.h,v 1.4 2009-11-30 02:27:59 fgygi Exp $
#ifndef SHAREDFILEPTR_H
#define SHAREDFILEPTR_H
#include<fstream>
#if USE_MPI
#include "mpi.h"
#else
typedef int MPI_Comm;
typedef std::ofstream MPI_File;
typedef long long int MPI_Offset;
#endif
class SharedFilePtr
{
......@@ -38,8 +46,10 @@ class SharedFilePtr
void sync(void)
{
// set all offsets to the largest offset
#if USE_MPI
long long int s_off = offset_;
MPI_Allreduce(&s_off,&offset_,1,MPI_LONG_LONG,MPI_MAX,comm_);
#endif
}
void set_offset(long long int off)
{
......
......@@ -15,7 +15,7 @@
// SlaterDet.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: SlaterDet.C,v 1.57 2009-08-26 15:03:50 fgygi Exp $
// $Id: SlaterDet.C,v 1.58 2009-11-30 02:30:34 fgygi Exp $
#include "SlaterDet.h"
#include "FourierTransform.h"
......@@ -1386,11 +1386,13 @@ void SlaterDet::write(SharedFilePtr& sfp, string encoding, double weight,
vector<double> wftmpr(wftmpr_loc_size);
Base64Transcoder xcdr;
#if USE_MPI
char* wbuf = 0;
size_t wbufsize = 0;
const Context& colctxt = basis_->context();
#endif
// Segment n on process iprow is sent to row (n*nprow+iprow)/(nprow)
const Context& colctxt = basis_->context();
const int nprow = ctxt_.nprow();
vector<int> scounts(nprow), sdispl(nprow), rcounts(nprow), rdispl(nprow);
......@@ -1653,6 +1655,7 @@ void SlaterDet::write(SharedFilePtr& sfp, string encoding, double weight,
// seg is defined
#if USE_MPI
// redistribute segments to tasks within each process column
for ( int i = 0; i < nprow; i++ )
......@@ -1708,7 +1711,12 @@ void SlaterDet::write(SharedFilePtr& sfp, string encoding, double weight,
wbufsize += rbufsize;
}
delete [] rbuf;
#else
sfp.file().write(seg.data(),seg.size());
#endif
}
#if USE_MPI
// wbuf now contains the data to be written in the correct order
ctxt_.barrier();
......@@ -1754,6 +1762,9 @@ void SlaterDet::write(SharedFilePtr& sfp, string encoding, double weight,
<< endl;
sfp.advance(s.size());
}
#else
sfp.file() << "</slater_determinant>\n";
#endif // USE_MPI
}
////////////////////////////////////////////////////////////////////////////////
......
......@@ -15,7 +15,7 @@
// UserInterface.C: definition of readCmd and processCmds
//
////////////////////////////////////////////////////////////////////////////////
// $Id: UserInterface.C,v 1.13 2009-03-08 01:12:33 fgygi Exp $
// $Id: UserInterface.C,v 1.14 2009-11-30 02:28:54 fgygi Exp $
#include "UserInterface.h"
#include "qbox_xmlns.h"
......@@ -27,7 +27,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#if USE_MPI
#include <mpi.h>
#endif
using namespace std;
////////////////////////////////////////////////////////////////////////////////
......@@ -49,8 +51,10 @@ void wait_for_no_file(const string& lockfilename)
////////////////////////////////////////////////////////////////////////////////
UserInterface::UserInterface(void) : terminate_(false)
{
int mype;
int mype = 0;
#if USE_MPI
MPI_Comm_rank(MPI_COMM_WORLD,&mype);
#endif
onpe0_ = ( mype == 0 );
}
......@@ -138,8 +142,10 @@ void UserInterface::processCmds ( istream &cmdstream, const char *prompt,
cmd_read = readCmd(cmdline, 256, cmdstream, echo );
done = !cmd_read;
}
#if USE_MPI
MPI_Bcast(&cmdline[0],256,MPI_CHAR,0,MPI_COMM_WORLD);
MPI_Bcast(&cmd_read,1,MPI_INT,0,MPI_COMM_WORLD);
#endif
if ( cmd_read )
{
......@@ -208,12 +214,16 @@ void UserInterface::processCmds ( istream &cmdstream, const char *prompt,
if ( cmdptr )
{
#if USE_MPI
MPI_Barrier(MPI_COMM_WORLD);
#endif
#if DEBUG
cout << " execute command " << cmdptr->name() << endl;
#endif
cmdptr->action(ac,av);
#if USE_MPI
MPI_Barrier(MPI_COMM_WORLD);
#endif
#if DEBUG
cout << " command completed" << cmdptr->name() << endl;
#endif
......@@ -227,7 +237,9 @@ void UserInterface::processCmds ( istream &cmdstream, const char *prompt,
cmdstr.open(av[0],ios::in);
status = !cmdstr;
}
#if USE_MPI
MPI_Bcast(&status,1,MPI_INT,0,MPI_COMM_WORLD);
#endif
if ( !status )
{
// create new prompt in the form: prompt<filename>
......@@ -267,7 +279,9 @@ void UserInterface::processCmds ( istream &cmdstream, const char *prompt,
if ( onpe0_ )
done |= terminate_;
#if USE_MPI
MPI_Bcast(&done,1,MPI_INT,0,MPI_COMM_WORLD);
#endif
}
if ( onpe0_ )
......@@ -334,8 +348,10 @@ void UserInterface::processCmdsServer ( string inputfilename,
cmd_read = readCmd(cmdline, 256, qbin, echo );
cout << prompt << " " << cmdline << endl;
}
#if USE_MPI
MPI_Bcast(&cmdline[0],256,MPI_CHAR,0,MPI_COMM_WORLD);
MPI_Bcast(&cmd_read,1,MPI_INT,0,MPI_COMM_WORLD);
#endif
if ( cmd_read )
{
......@@ -410,12 +426,16 @@ void UserInterface::processCmdsServer ( string inputfilename,
if ( cmdptr )
{
#if USE_MPI
MPI_Barrier(MPI_COMM_WORLD);
#endif
#if DEBUG
cerr << " execute command " << cmdptr->name() << endl;
#endif
cmdptr->action(ac,av);
#if USE_MPI
MPI_Barrier(MPI_COMM_WORLD);
#endif
#if DEBUG
cerr << " command completed " << cmdptr->name() << endl;
#endif
......@@ -429,7 +449,9 @@ void UserInterface::processCmdsServer ( string inputfilename,
cmdstr.open(av[0],ios::in);
status = !cmdstr;
}
#if USE_MPI
MPI_Bcast(&status,1,MPI_INT,0,MPI_COMM_WORLD);
#endif
if ( !status )
{
// create new prompt in the form: prompt<filename>
......@@ -465,7 +487,9 @@ void UserInterface::processCmdsServer ( string inputfilename,
// check if terminate_ flag was set during command execution
if ( onpe0_ )
done = terminate_;
#if USE_MPI
MPI_Bcast(&done,1,MPI_INT,0,MPI_COMM_WORLD);
#endif
} // if cmd_read
......
......@@ -15,7 +15,7 @@
// Wavefunction.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: Wavefunction.C,v 1.36 2008-09-08 15:56:19 fgygi Exp $
// $Id: Wavefunction.C,v 1.37 2009-11-30 02:27:59 fgygi Exp $
#include "Wavefunction.h"
#include "SlaterDet.h"
......@@ -700,12 +700,16 @@ void Wavefunction::write(SharedFilePtr& sfp, string encoding, string tag) const
<< " nz=\"" << sd_[0][0]->basis().np(2) << "\"/>" << endl;
string str(os.str());
int len = str.size();
#if USE_MPI
MPI_Status status;
int err = MPI_File_write_at(sfp.file(),sfp.mpi_offset(),(void*)str.c_str(),
len,MPI_CHAR,&status);
if ( err != 0 )
cout << " Wavefunction::write: error in MPI_File_write" << endl;
sfp.advance(len);
#else
sfp.file().write(str.c_str(),len);
#endif
}
for ( int ispin = 0; ispin < nspin_; ispin++ )
......@@ -724,12 +728,16 @@ void Wavefunction::write(SharedFilePtr& sfp, string encoding, string tag) const
os << "</" << tag << ">" << endl;
string str(os.str());
int len = str.size();
#if USE_MPI
MPI_Status status;
int err = MPI_File_write_at(sfp.file(),sfp.mpi_offset(),(void*)str.c_str(),
len,MPI_CHAR,&status);
if ( err != 0 )
cout << " Wavefunction::write: error in MPI_File_write" << endl;
sfp.advance(len);
#else
sfp.file().write(str.c_str(),len);
#endif
}
}
......
......@@ -15,17 +15,17 @@
// Wavefunction.h
//
////////////////////////////////////////////////////////////////////////////////
// $Id: Wavefunction.h,v 1.22 2008-09-08 15:56:19 fgygi Exp $
// $Id: Wavefunction.h,v 1.23 2009-11-30 02:27:59 fgygi Exp $
#ifndef WAVEFUNCTION_H
#define WAVEFUNCTION_H
#include "D3vector.h"
#include "UnitCell.h"
#include "SharedFilePtr.h"
#include <vector>
#include <complex>
class SharedFilePtr;
class SlaterDet;
class Context;
......
......@@ -15,7 +15,7 @@
// XMLGFPreprocessor.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: XMLGFPreprocessor.C,v 1.15 2008-11-14 04:04:03 fgygi Exp $
// $Id: XMLGFPreprocessor.C,v 1.16 2009-11-30 02:26:37 fgygi Exp $
#include <cassert>
#include <iostream>
......@@ -942,6 +942,7 @@ void XMLGFPreprocessor::process(const char* const filename,
}
}
#if USE_MPI
// send scount array using all_to_all call
valarray<int> a2a_scounts(1,ctxt.size()),a2a_rcounts(1,ctxt.size()),
a2a_sdispl(0,ctxt.size()),a2a_rdispl(0,ctxt.size());
......@@ -968,11 +969,14 @@ void XMLGFPreprocessor::process(const char* const filename,
valarray<double> rbuf(rbufsize);
status = MPI_Alltoallv(&sbuf[0],&scounts[0],&sdispl[0],MPI_DOUBLE,
&rbuf[0],&rcounts[0],&rdispl[0],MPI_DOUBLE,rctxt.comm());
assert(status==0);
#else // USE_MPI
valarray<double> rbuf(sbuf);
#endif // USE_MPI
// copy data from rbuf to gfdata.valptr()
// functions in rbuf can have varying length
// determine bounds igfmin, igfmax of functions in rbuf
......@@ -1061,6 +1065,7 @@ void XMLGFPreprocessor::process(const char* const filename,
// Distribute sizes of local strings to all tasks
// and store in array rcounts
#if USE_MPI
int xmlcontentsize = buf.size();
status = MPI_Allgather(&xmlcontentsize,1,MPI_INT,&rcounts[0],1,
MPI_INT,rctxt.comm());
......@@ -1079,7 +1084,9 @@ void XMLGFPreprocessor::process(const char* const filename,
// Allgatherv xml content
status = MPI_Allgatherv(&buf[0],xmlcontentsize,MPI_CHAR,&xmlcontent[0],
&rcounts[0],&rdispl[0],MPI_CHAR,rctxt.comm());
#else
xmlcontent = buf;
#endif // USE_MPI
tm.stop();
if ( ctxt.onpe0() )
cout << " XMLGFPreprocessor: XML compacting time: " << tm.real() << endl;
......
......@@ -15,7 +15,7 @@
// testChargeDensity.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: testChargeDensity.C,v 1.4 2008-09-08 15:56:20 fgygi Exp $
// $Id: testChargeDensity.C,v 1.5 2009-11-30 02:26:07 fgygi Exp $
#include "Context.h"
#include "Wavefunction.h"
......@@ -85,7 +85,7 @@ int main(int argc, char **argv)
{
for ( int ikp = 0; ikp < wf.nkp(); ikp++ )
{
if ( wf.sd(ispin,ikp) != 0 && wf.sdcontext(ispin,ikp)->active() )
if ( wf.sd(ispin,ikp) != 0 && wf.sd(ispin,ikp)->context().active() )
{
cout << "wf.sd(ispin=" << ispin << ",ikp=" << ikp << "): "
<< wf.sd(ispin,ikp)->c().m() << "x"
......@@ -110,7 +110,7 @@ int main(int argc, char **argv)
cout << " wf.gram: CPU/Real: "
<< tm.cpu() << " / " << tm.real() << endl;
wf.update_occ();
// wf.update_occ();
// compute charge density in real space
Timer tmrho;
......
......@@ -45,9 +45,13 @@ int main(int argc, char **argv)
// the MPI_Finalize call
{
#if USE_MPI
char processor_name[MPI_MAX_PROCESSOR_NAME];
int namelen;
PMPI_Get_processor_name(processor_name,&namelen);
#else
const char* processor_name = "serial";
#endif
Context ctxt_global;
int mype = ctxt_global.mype();
......@@ -80,6 +84,7 @@ int main(int argc, char **argv)
else
{
cout << " use: testFourierTransform a b c ecut(a.u.) [kpoint] " << endl;
return 1;
}
UnitCell cell(a,b,c);
const double omega = cell.volume();
......@@ -146,7 +151,7 @@ int main(int argc, char **argv)
cout << " backward done " << endl;
ctxt.barrier();
#if 0
#if 1
tm.reset();
ft2.reset_timers();
......
......@@ -15,13 +15,14 @@
// testSample.C
//
////////////////////////////////////////////////////////////////////////////////
// $Id: testSample.C,v 1.5 2008-09-08 15:56:20 fgygi Exp $
// $Id: testSample.C,v 1.6 2009-11-30 02:23:26 fgygi Exp $
#include <iostream>
using namespace std;
#include "Context.h"
#include "SlaterDet.h"
#include "UnitCell.h"
#include "Sample.h"
#include "D3vector.h"
......@@ -35,21 +36,26 @@ int main(int argc, char** argv)
{
Context ctxt;
#if USE_MPI
char processor_name[MPI_MAX_PROCESSOR_NAME];
int namelen;
PMPI_Get_processor_name(processor_name,&namelen);
cout << " Process " << ctxt.mype() << " on " << processor_name << endl;
#endif
Sample s(ctxt);
D3vector cell(18,18,18);
D3vector a(18, 0, 0);
D3vector b( 0,18, 0);
D3vector c( 0, 0,18);
UnitCell uc(a,b,c);
double ecut = 25.0;
s.wf.resize(cell,cell,ecut);
s.wf.resize(uc,uc,ecut);
s.wf.set_nel(12*54);
s.wf.randomize(1.e-4);
s.wf.gram();
cout << " ortho_error: " << s.wf.sd[0][0]->ortho_error() << endl;
cout << " ortho_error: " << s.wf.sd(0,0)->ortho_error() << endl;
}
#if USE_MPI
MPI_Finalize();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment