openCARP
Doxygen code documentation for the open cardiac electrophysiology simulator openCARP
SF_abstract_vector.h
Go to the documentation of this file.
1 // ----------------------------------------------------------------------------
2 // openCARP is an open cardiac electrophysiology simulator.
3 //
4 // Copyright (C) 2020 openCARP project
5 //
6 // This program is licensed under the openCARP Academic Public License (APL)
7 // v1.0: You can use and redistribute it and/or modify it in non-commercial
8 // academic environments under the terms of APL as published by the openCARP
9 // project v1.0, or (at your option) any later version. Commercial use requires
10 // a commercial license (info@opencarp.org).
11 //
12 // This program is distributed without any warranty; see the openCARP APL for
13 // more details.
14 //
15 // You should have received a copy of the openCARP APL along with this program
16 // and can find it online: http://www.opencarp.org/license
17 // ----------------------------------------------------------------------------
18 
19 #ifndef _SF_ABSTRACT_VECTOR_H
20 #define _SF_ABSTRACT_VECTOR_H
21 
22 #include <mpi.h>
23 
24 #include <petscvec.h> // TODO: For scattering, VecScatter and friends
25 #include <petscis.h>
26 #include <petscsys.h> // TODO: For PETSC_COMM_WORLD
27 
28 #include "SF_container.h"
29 #include "SF_globals.h"
30 #include "SF_parallel_layout.h"
31 #include "SF_parallel_utils.h"
32 #include "mpi_utils.h"
33 #include "petsc_utils.h"
34 
35 #include "hashmap.hpp"
36 
37 namespace SF {
38 
39 // Forward declare the scattering class
40 class scattering;
41 
55 template<class T, class S>
57 
58  public:
59 
62 
64  int dpn = 0;
66 
68  virtual ~abstract_vector() = default;
69 
77  virtual void init(const meshdata<mesh_int_t, mesh_real_t>& imesh,
78  int idpn,
79  ltype inp_layout) = 0;
80 
86  virtual void init(const abstract_vector<T, S>& vec) = 0;
87 
96  virtual void init(T igsize, T ilsize, int idpn = 1, ltype ilayout = unset) = 0;
97 
107  inline std::tuple<T, T> init_common(const meshdata<mesh_int_t, mesh_real_t>& imesh,
108  int idpn,
109  ltype inp_layout)
110  {
111  mesh = &imesh;
112  dpn = idpn;
113  T N = 0, n = 0;
114 
115  switch(inp_layout) {
116  case algebraic:
117  N = static_cast<T>(mesh->pl.num_global_idx()) * static_cast<T>(dpn);
118  n = static_cast<T>(mesh->pl.num_algebraic_idx()) * static_cast<T>(dpn);
119  layout = algebraic;
120  break;
121 
122  case nodal:
123  N = static_cast<T>(mesh->l_numpts) * static_cast<T>(dpn);
124  MPI_Allreduce(MPI_IN_PLACE, &N, 1, opencarp::mpi_datatype<T>(), MPI_SUM, mesh->comm);
125  n = static_cast<T>(mesh->l_numpts) * static_cast<T>(dpn);
126  layout = nodal;
127  break;
128 
129  case elemwise:
130  N = static_cast<T>(mesh->g_numelem*dpn);
131  n = static_cast<T>(mesh->l_numelem*dpn);
132  layout = elemwise;
133  break;
134 
135  default: break;
136  }
137 
138  return std::tuple<T, T>(N, n);
139  }
140 
149  virtual void set(const vector<T>& idx, const vector<S>& vals, const bool additive = false, const bool local = false) = 0;
150 
159  virtual void set(const vector<T>& idx, const S val, const bool additive = false, const bool local = false) = 0;
160 
166  virtual void set(const S val) = 0;
167 
176  virtual void set(const T idx, const S val) = 0;
177 
185  virtual void get(const vector<T> & idx, S *out) = 0;
186 
194  virtual S get(const T idx) = 0;
195 
201  virtual void operator*=(const S sca) = 0;
202 
208  virtual void operator /= (const S sca) = 0;
209 
215  virtual void operator*=(const abstract_vector<T, S>& vec) = 0;
216 
223  virtual void add_scaled(const abstract_vector<T, S>& vec, S k) = 0;
224 
230  virtual void operator += (const abstract_vector<T,S> & vec) = 0;
231 
237  virtual void operator-=(const abstract_vector<T, S>& vec) = 0;
238 
244  virtual void operator+=(S c) = 0;
245 
251  virtual void operator=(const vector<S>& rhs) = 0;
252 
258  virtual void operator=(const abstract_vector<T, S>& rhs) = 0;
259 
267  virtual void shallow_copy(const abstract_vector<T, S>& v) = 0;
268 
276  virtual void deep_copy(const abstract_vector<T, S>& v) = 0;
277 
290  virtual void overshadow(const abstract_vector<T, S>& sub, bool member, int offset, int sz, bool share) = 0;
291 
297  virtual T lsize() const = 0;
298 
304  virtual T gsize() const = 0;
305 
312  virtual void get_ownership_range(T& start, T& stop) const = 0;
313 
321  virtual S* ptr() = 0;
322 
331  virtual const S* const_ptr() const = 0;
332 
341  virtual S* device_ptr() = 0;
342 
350  virtual void release_ptr(S*& p) = 0;
351 
359  virtual void const_release_ptr(const S*& p) const = 0;
360 
368  virtual void release_device_ptr(S*& p) = 0;
369 
375  virtual S mag() const = 0;
376 
382  virtual S sum() const = 0;
383 
389  virtual S min() const = 0;
390 
398  virtual S dot(const abstract_vector<T, S>& v) const = 0;
399 
405  virtual bool is_init() const = 0;
406 
412  virtual std::string to_string() const = 0;
413 
419  virtual bool equals(const abstract_vector<T,S> & rhs) const = 0;
420 
424  virtual void finish_assembly() = 0;
425 
433  virtual void forward(abstract_vector<T, S>& out, scattering &sc, bool add = false) = 0;
434 
442  virtual void backward(abstract_vector<T,S> & out, scattering &sc, bool add = false) = 0;
443 
450  virtual void apply_scattering(scattering& sc, bool fwd) = 0;
451 
460  inline size_t write_ascii(const char* file, bool write_header)
461  {
462  int size, rank;
463  MPI_Comm comm = this->mesh != NULL ? this->mesh->comm : PETSC_COMM_WORLD;
464  MPI_Comm_rank(comm, &rank);
465  MPI_Comm_size(comm, &size);
466  const MPI_Datatype mpi_t = opencarp::mpi_datatype<T>();
467 
468  T glb_size = this->gsize();
469  T loc_size = this->lsize();
470 
471  int err = 0;
472  FILE* fd = NULL;
473  long int nwr = 0;
474 
475  if(rank == 0) {
476  fd = fopen(file, "w");
477  if(!fd) err = 1;
478  }
479 
480  MPI_Allreduce(MPI_IN_PLACE, &err, 1, MPI_INT, MPI_MAX, comm);
481  if(err) {
482  treat_file_open_error(file, __func__, errno, false, rank);
483  return nwr;
484  }
485 
486  S* p = this->ptr();
487 
488  if(rank == 0) {
489  if(write_header)
490  fprintf(fd, "%jd\n", opencarp::printable_int(glb_size));
491 
492  for(T i=0; i<loc_size/this->dpn; i++) {
493  for(int j=0; j<this->dpn; j++)
494  nwr += fprintf(fd, "%f ", p[i*this->dpn+j]);
495  nwr += fprintf(fd, "\n");
496  }
497 
498  vector<S> wbuff;
499  for(int pid=1; pid < size; pid++)
500  {
501  T rsize;
502  MPI_Status stat;
503 
504  MPI_Recv(&rsize, 1, mpi_t, pid, SF_MPITAG, comm, &stat);
505  wbuff.resize(rsize);
506  MPI_Recv(wbuff.data(), rsize*sizeof(S), MPI_BYTE, pid, SF_MPITAG, comm, &stat);
507 
508  for(T i=0; i<rsize/this->dpn; i++) {
509  for(int j=0; j<this->dpn; j++)
510  nwr += fprintf(fd, "%f ", wbuff[i*this->dpn+j]);
511  nwr += fprintf(fd, "\n");
512  }
513  }
514  fclose(fd);
515  }
516  else {
517  MPI_Send(&loc_size, 1, mpi_t, 0, SF_MPITAG, comm);
518  MPI_Send(p, loc_size*sizeof(S), MPI_BYTE, 0, SF_MPITAG, comm);
519  }
520 
521  this->release_ptr(p);
522  MPI_Bcast(&nwr, 1, MPI_LONG, 0, comm);
523 
524  return nwr;
525  }
526 
534  template<typename V>
535  inline size_t write_binary(FILE* fd)
536  {
537  int size, rank;
538  MPI_Comm comm = this->mesh != NULL ? this->mesh->comm : PETSC_COMM_WORLD;
539  MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm, &size);
540 
541  long int loc_size = this->lsize();
542  S* p = this->ptr();
543 
544  vector<V> buff(loc_size);
545  for(long int i=0; i<loc_size; i++) buff[i] = p[i];
546 
547  long int nwr = root_write(fd, buff, comm);
548 
549  this->release_ptr(p);
550  return nwr;
551  }
552 
554  template<typename V>
555  inline size_t write_binary(std::string file)
556  {
557  size_t nwr = 0;
558  MPI_Comm comm = this->mesh != NULL ? this->mesh->comm : PETSC_COMM_WORLD;
559  int rank; MPI_Comm_rank(comm, &rank);
560 
561  FILE* fd = NULL;
562  int error = 0;
563 
564  if(rank == 0) {
565  fd = fopen(file.c_str(), "w");
566  if(fd == NULL)
567  error++;
568  }
569 
570  MPI_Allreduce(MPI_IN_PLACE, &error, 1, MPI_INT, MPI_SUM, comm);
571 
572  if(error == 0) {
573  nwr = this->write_binary<V>(fd);
574  fclose(fd);
575  }
576  else {
577  treat_file_open_error(file.c_str(), __func__, errno, false, rank);
578  }
579 
580  return nwr;
581  }
582 
583  template<typename V>
584  inline size_t read_binary(FILE* fd)
585  {
586  MPI_Comm comm = this->mesh != NULL ? this->mesh->comm : PETSC_COMM_WORLD;
587 
588  size_t loc_size = this->lsize();
589  S* p = this->ptr();
590  vector<V> buff(loc_size);
591 
592  size_t nrd = root_read(fd, buff, comm);
593 
594  for(size_t i=0; i<loc_size; i++)
595  p[i] = buff[i];
596 
597  this->release_ptr(p);
598 
599  return nrd;
600  }
601 
602  template<typename V>
603  inline size_t read_binary(std::string file)
604  {
605  MPI_Comm comm = mesh != NULL ? mesh->comm : PETSC_COMM_WORLD;
606 
607  size_t nrd = 0;
608  int rank; MPI_Comm_rank(comm, &rank);
609 
610  FILE* fd = NULL;
611  int error = 0;
612 
613  if(rank == 0) {
614  fd = fopen(file.c_str(), "r");
615  if(fd == NULL)
616  error++;
617  }
618 
619  MPI_Allreduce(MPI_IN_PLACE, &error, 1, MPI_INT, MPI_SUM, comm);
620 
621  if(error == 0) {
622  nrd = read_binary<V>(fd);
623  fclose(fd);
624  }
625  else {
626  treat_file_open_error(file.c_str(), __func__, errno, false, rank);
627  }
628 
629  return nrd;
630  }
631 
632  inline size_t read_ascii(FILE* fd)
633  {
634  MPI_Comm comm = this->mesh != NULL ? this->mesh->comm : PETSC_COMM_WORLD;
635 
636  size_t loc_size = this->lsize();
637  S* p = this->ptr();
638 
639  size_t nrd = root_read_ascii(fd, p, loc_size, comm, false);
640  this->release_ptr(p);
641  return nrd;
642  }
643 
644  inline size_t read_ascii(std::string file)
645  {
646  MPI_Comm comm = this->mesh != NULL ? this->mesh->comm : PETSC_COMM_WORLD;
647  int rank; MPI_Comm_rank(comm, &rank);
648 
649  size_t nrd = 0;
650 
651  FILE* fd = NULL;
652  int error = 0;
653 
654  if(rank == 0) {
655  fd = fopen(file.c_str(), "r");
656  if(fd == NULL)
657  error++;
658  }
659 
660  MPI_Allreduce(MPI_IN_PLACE, &error, 1, MPI_INT, MPI_SUM, comm);
661 
662  if(error == 0) {
663  nrd = read_ascii(fd);
664  if(fd) fclose(fd);
665  }
666  else {
667  treat_file_open_error(file.c_str(), __func__, errno, false, rank);
668  }
669 
670  return nrd;
671  }
672 };
673 
674 
677 template<class T, class S>
678 inline bool is_init(const abstract_vector<T,S>* v)
679 {
680  return (v && v->is_init());
681 }
682 
683 
684 // TODO: This is a type of Vector and can most likely be integrated into the
685 // `abstract_vector` type in some way. Everything here and also in
686 // `SF_parallel_layout.h` probably need to be abstracted away, or made less
687 // PETSc specific?
696 {
697  public:
698  Vec b_buff;
699  VecScatter vec_sc;
700 
702 
704  scattering() : b_buff(NULL), vec_sc(NULL)
705  {}
706 
709  {
710  if(b_buff) PETSC_CHECK(VecDestroy(&b_buff));
711  if(vec_sc) PETSC_CHECK(VecScatterDestroy(&vec_sc));
712  }
719  template<class T, class S>
720  inline void forward(abstract_vector<T,S> & in, abstract_vector<T,S> & out, bool add = false)
721  {
722  in.forward(out, *this, add);
723  }
724 
731  template<class T, class S>
732  inline void backward(abstract_vector<T,S> & in, abstract_vector<T,S> & out, bool add = false)
733  {
734  in.backward(out, *this, add);
735  }
736 
743  template<class T, class S>
744  inline void operator()(abstract_vector<T,S> & v, bool fwd)
745  {
746  v.apply_scattering(*this, fwd);
747  }
748 };
749 
759 {
760  private:
763 
764  public:
777  template<class T> inline scattering*
779  const vector<T> & nbr_a,
780  const vector<T> & nbr_b,
781  const size_t gsize_a,
782  const size_t gsize_b,
783  const short dpn)
784  {
785  assert(_registry.count(spec) == 0);
786 
787  scattering* sc = new scattering();
788  _registry[spec] = sc;
789 
790  IS is_a, is_b;
791  vector<SF_int> idx_a(nbr_a.size() * dpn);
792  vector<SF_int> idx_b(nbr_b.size() * dpn);
793 
794  // we copy indexing into new containers because of dpn and also
795  // because of the implicit typecast between T and SF_int
796  for(size_t i=0; i<nbr_a.size(); i++)
797  for(short j=0; j<dpn; j++) idx_a[i*dpn+j] = nbr_a[i]*dpn+j;
798 
799  for(size_t i=0; i<nbr_b.size(); i++)
800  for(short j=0; j<dpn; j++) idx_b[i*dpn+j] = nbr_b[i]*dpn+j;
801 
802  PETSC_CHECK(ISCreateGeneral(PETSC_COMM_WORLD, idx_a.size(), idx_a.data(), PETSC_COPY_VALUES, &is_a));
803  PETSC_CHECK(ISCreateGeneral(PETSC_COMM_WORLD, idx_b.size(), idx_b.data(), PETSC_COPY_VALUES, &is_b));
804 
805  PETSC_CHECK(ISSetPermutation(is_b));
806 
807  Vec a;
808  PETSC_CHECK(VecCreateMPI(PETSC_COMM_WORLD, idx_a.size(), gsize_a*dpn, &a));
809  PETSC_CHECK(VecCreateMPI(PETSC_COMM_WORLD, idx_b.size(), gsize_b*dpn, &sc->b_buff));
810  PETSC_CHECK(VecSetFromOptions(a));
811  PETSC_CHECK(VecSetFromOptions(sc->b_buff));
812 
813  PETSC_CHECK(VecScatterCreate(a, is_a, sc->b_buff, is_b, &sc->vec_sc));
814 
815  PETSC_CHECK(VecDestroy(&a));
816  PETSC_CHECK(ISDestroy (&is_a));
817  PETSC_CHECK(ISDestroy (&is_b));
818 
819  sc->idx_a.assign(idx_a.begin(), idx_a.end());
820  sc->idx_b.assign(idx_b.begin(), idx_b.end());
821 
822  return sc;
823  }
824 
825 
831  template<class T> inline scattering*
833  const vector<T> & layout_a,
834  const vector<T> & layout_b,
835  const vector<T> & idx_a,
836  const vector<T> & idx_b,
837  const int rank,
838  const int dpn)
839  {
840  // scattering spec must not exist yet
841  assert(_registry.count(spec) == 0);
842 
843  // the local index sets have to be of equal size.
844  assert(idx_a.size() == idx_b.size());
845 
846  scattering* sc = new scattering();
847  _registry[spec] = sc;
848 
849  IS is_a, is_b;
850  Vec a;
851  vector<SF_int> sidx_a(idx_a.size() * dpn);
852  vector<SF_int> sidx_b(idx_b.size() * dpn);
853 
854  T lsize_a = layout_a[rank+1] - layout_a[rank];
855  T lsize_b = layout_b[rank+1] - layout_b[rank];
856  T gsize_a = layout_a[layout_a.size()-1];
857  T gsize_b = layout_b[layout_a.size()-1];
858 
859  // we copy indexing into new containers because of dpn and also
860  // because of the implicit typecast between T and SF_int
861  for(size_t i=0; i<idx_a.size(); i++)
862  for(short j=0; j<dpn; j++) sidx_a[i*dpn+j] = idx_a[i]*dpn+j;
863 
864  for(size_t i=0; i<idx_b.size(); i++)
865  for(short j=0; j<dpn; j++) sidx_b[i*dpn+j] = idx_b[i]*dpn+j;
866 
867  PETSC_CHECK(ISCreateGeneral(PETSC_COMM_WORLD, sidx_a.size(), sidx_a.data(), PETSC_COPY_VALUES, &is_a));
868  PETSC_CHECK(ISCreateGeneral(PETSC_COMM_WORLD, sidx_b.size(), sidx_b.data(), PETSC_COPY_VALUES, &is_b));
869 
870  PETSC_CHECK(VecCreateMPI(PETSC_COMM_WORLD, lsize_a*dpn, gsize_a*dpn, &a));
871  PETSC_CHECK(VecCreateMPI(PETSC_COMM_WORLD, lsize_b*dpn, gsize_b*dpn, &sc->b_buff));
872  PETSC_CHECK(VecSetFromOptions(a));
873  PETSC_CHECK(VecSetFromOptions(sc->b_buff));
874 
875  PETSC_CHECK(VecScatterCreate(a, is_a, sc->b_buff, is_b, &sc->vec_sc));
876 
877  PETSC_CHECK(VecDestroy(&a));
878  PETSC_CHECK(ISDestroy (&is_a));
879  PETSC_CHECK(ISDestroy (&is_b));
880 
881  sc->idx_a.assign(idx_a.begin(), idx_a.end());
882  sc->idx_b.assign(idx_b.begin(), idx_b.end());
883 
884  return sc;
885  }
886 
898  {
899  scattering* ret = NULL;
900 
901  // scattering must be present
902  if(_registry.count(spec))
903  ret = _registry[spec];
904 
905  return ret;
906  }
907 
911  inline void free_scatterings()
912  {
913  typename hashmap::unordered_map<quadruple<int>,scattering*>::iterator it;
914  for(it = _registry.begin(); it != _registry.end(); ++it) {
915  if(it->second) {
916  delete it->second;
917  it->second = NULL;
918  }
919  }
920  }
921 };
922 
923 
924 } // namespace SF
925 
926 
927 #endif // _SF_ABSTRACT_VECTOR_H
Basic containers.
#define SF_MPITAG
the MPI tag when communicating
Definition: SF_globals.h:30
Classes and algorithms related to the layout of distributed meshes.
Simple utility functions for parallel data.
size_t read_ascii(FILE *fd)
size_t read_binary(std::string file)
virtual void get(const vector< T > &idx, S *out)=0
virtual void apply_scattering(scattering &sc, bool fwd)=0
virtual S mag() const =0
virtual S * ptr()=0
virtual void operator-=(const abstract_vector< T, S > &vec)=0
virtual void release_ptr(S *&p)=0
virtual std::string to_string() const =0
virtual S min() const =0
virtual void operator*=(const abstract_vector< T, S > &vec)=0
virtual S sum() const =0
virtual T gsize() const =0
size_t write_ascii(const char *file, bool write_header)
virtual void init(T igsize, T ilsize, int idpn=1, ltype ilayout=unset)=0
size_t read_binary(FILE *fd)
virtual void operator/=(const S sca)=0
virtual void forward(abstract_vector< T, S > &out, scattering &sc, bool add=false)=0
virtual bool is_init() const =0
ltype layout
used vector layout (nodal, algebraic, unset)
virtual S * device_ptr()=0
virtual bool equals(const abstract_vector< T, S > &rhs) const =0
virtual void const_release_ptr(const S *&p) const =0
size_t read_ascii(std::string file)
virtual void operator=(const abstract_vector< T, S > &rhs)=0
virtual void deep_copy(const abstract_vector< T, S > &v)=0
size_t write_binary(std::string file)
write binary. Open file descriptor myself.
virtual void get_ownership_range(T &start, T &stop) const =0
virtual S get(const T idx)=0
virtual void set(const vector< T > &idx, const S val, const bool additive=false, const bool local=false)=0
virtual void shallow_copy(const abstract_vector< T, S > &v)=0
std::tuple< T, T > init_common(const meshdata< mesh_int_t, mesh_real_t > &imesh, int idpn, ltype inp_layout)
virtual void add_scaled(const abstract_vector< T, S > &vec, S k)=0
virtual void overshadow(const abstract_vector< T, S > &sub, bool member, int offset, int sz, bool share)=0
virtual void release_device_ptr(S *&p)=0
virtual void set(const S val)=0
virtual ~abstract_vector()=default
virtual void operator+=(const abstract_vector< T, S > &vec)=0
virtual void operator=(const vector< S > &rhs)=0
virtual void set(const T idx, const S val)=0
size_t write_binary(FILE *fd)
Write a vector to HD in binary. File descriptor is already set up.
virtual void backward(abstract_vector< T, S > &out, scattering &sc, bool add=false)=0
virtual T lsize() const =0
virtual void init(const abstract_vector< T, S > &vec)=0
int dpn
d.o.f. per mesh vertex; data is stored node-major (index = node*dpn + component).
virtual const S * const_ptr() const =0
virtual void set(const vector< T > &idx, const vector< S > &vals, const bool additive=false, const bool local=false)=0
virtual void operator*=(const S sca)=0
virtual void finish_assembly()=0
virtual void init(const meshdata< mesh_int_t, mesh_real_t > &imesh, int idpn, ltype inp_layout)=0
const meshdata< mesh_int_t, mesh_real_t > * mesh
the connected mesh
virtual void operator+=(S c)=0
virtual S dot(const abstract_vector< T, S > &v) const =0
overlapping_layout< T > pl
nodal parallel layout
Definition: SF_container.h:429
size_t l_numelem
local number of elements
Definition: SF_container.h:399
size_t l_numpts
local number of points
Definition: SF_container.h:401
size_t g_numelem
global number of elements
Definition: SF_container.h:398
MPI_Comm comm
the parallel mesh is defined on a MPI world
Definition: SF_container.h:404
The scatterer registry class.
void free_scatterings()
Free the registered scatterings.
scattering * register_scattering(const quadruple< int > spec, const vector< T > &layout_a, const vector< T > &layout_b, const vector< T > &idx_a, const vector< T > &idx_b, const int rank, const int dpn)
Register a scattering.
scattering * register_permutation(const quadruple< int > spec, const vector< T > &nbr_a, const vector< T > &nbr_b, const size_t gsize_a, const size_t gsize_b, const short dpn)
Register a permutation scattering.
scattering * get_scattering(const quadruple< int > spec)
Access an previously registered scattering.
Container for a PETSc VecScatter.
vector< SF_int > idx_a
~scattering()
Destructor.
vector< SF_int > idx_b
scattering()
Constructor.
Vec b_buff
A buffer vector which also defines the parallel layout of the "b" side.
void operator()(abstract_vector< T, S > &v, bool fwd)
Apply the scattering on a data vector.
void forward(abstract_vector< T, S > &in, abstract_vector< T, S > &out, bool add=false)
Forward scattering.
VecScatter vec_sc
The scatterer.
void backward(abstract_vector< T, S > &in, abstract_vector< T, S > &out, bool add=false)
Backward scattering.
A vector storing arbitrary data.
Definition: SF_vector.h:43
size_t size() const
The current size of the vector.
Definition: SF_vector.h:104
void resize(size_t n)
Resize a vector.
Definition: SF_vector.h:209
const T * end() const
Pointer to the vector's end.
Definition: SF_vector.h:128
void assign(InputIterator s, InputIterator e)
Assign a memory range.
Definition: SF_vector.h:161
const T * begin() const
Pointer to the vector's start.
Definition: SF_vector.h:116
T * data()
Pointer to the vector's start.
Definition: SF_vector.h:91
hm_int count(const K &key) const
Check if key exists.
Definition: hashmap.hpp:627
Classes similar to unordered_set and unordered_map, but with better performance.
Definition: dense_mat.hpp:34
void treat_file_open_error(const char *file, const char *caller, const int errnum, const bool do_exit, int rank)
treat a file open error by displaying the errnum string interpretation and the caller
Definition: SF_io_base.h:83
bool is_init(const abstract_vector< T, S > *v)
size_t root_read(FILE *fd, vector< V > &vec, MPI_Comm comm)
Read binary data into a vector.
size_t root_read_ascii(FILE *fd, vector< V > &vec, MPI_Comm comm, bool int_data)
Read binary data into a vector.
size_t root_write(FILE *fd, const vector< V > &vec, MPI_Comm comm)
Write vector data binary to disk.
std::intmax_t printable_int(T value)
Definition: mpi_utils.h:130