Ejemplo n.º 1
0
/* internal p3m-specific tuning function */
FCSResult fcs_p3m_tune(FCS handle, 
		       fcs_int local_particles,
		       fcs_float *positions, fcs_float *charges)
{
  char* fnc_name = "fcs_p3m_tune";
  FCSResult result;
  result = fcs_p3m_check(handle, fnc_name);
  if (result != NULL) return result;

  /* Handle periodicity */
  const fcs_int *periodicity = fcs_get_periodicity(handle);
  if (! (periodicity[0] && periodicity[1] && periodicity[2]))
    return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, fnc_name, 
      "p3m requires periodic boundary conditions.");
    
  /* Handle box size */
  const fcs_float *a = fcs_get_box_a(handle);
  const fcs_float *b = fcs_get_box_b(handle);
  const fcs_float *c = fcs_get_box_c(handle);
  if (!fcs_is_orthogonal(a, b, c)){
        if (ifcs_p3m_check_triclinic_box(a[1],a[2],b[2])){
            
            if(ifcs_p3m_set_triclinic_flag(handle->method_context)!=NULL)
           return ifcs_p3m_set_triclinic_flag(handle->method_context);           
        }
        else
            return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, fnc_name,
                "p3m triclinic requires the box to be as follows: \n \
                the first box vector is parallel to the x axis\n \
                the second box vector is in the yz plane.");
    } else {
        if (!fcs_uses_principal_axes(a, b, c))
Ejemplo n.º 2
0
FCSResult fcs_mmm1d_tune(FCS handle, 
		       fcs_int local_particles, fcs_int local_max_particles, 
		       fcs_float *positions, fcs_float *charges)
{
  char* fnc_name = "fcs_mmm1d_tune";
  FCSResult result;
  
  result = fcs_mmm1d_check(handle, fnc_name);
  if (result != NULL) return result;
  
  /* Check box periodicity */
  fcs_int *periodicity = fcs_get_periodicity(handle);
  if (periodicity[0] != 0 ||
      periodicity[1] != 0 ||
      periodicity[2] != 1)
    return fcsResult_create(FCS_LOGICAL_ERROR, fnc_name, "mmm1d requires z-axis periodic boundary.");
  
  /* Check box shape */
  fcs_float *a = fcs_get_box_a(handle);
  fcs_float *b = fcs_get_box_b(handle);
  fcs_float *c = fcs_get_box_c(handle);
  if (!fcs_is_cubic(a, b, c))
    return fcsResult_create(FCS_LOGICAL_ERROR, fnc_name, "mmm1d requires a cubic box.");
  
  mmm1d_set_box_a(handle->method_context, a[0]);
  mmm1d_set_box_b(handle->method_context, b[1]);
  mmm1d_set_box_c(handle->method_context, c[2]);
  
  /* Effectively, tune initializes the algorithm */
  result = mmm1d_tune(handle->method_context, 
        local_particles,
        positions, charges);
  
  return result;
}
Ejemplo n.º 3
0
/**
 * print the parameters of an FCS solver to stdout
 */
FCSResult fcs_print_parameters(FCS handle)
{
  const char *fnc_name = "fcs_print_parameters";
  FCSResult result;

  CHECK_HANDLE_RETURN_RESULT(handle, fnc_name);

  printf("chosen method: %s\n", fcs_get_method_name(handle));

  printf("near field computations done by solver: %c\n", (fcs_get_near_field_flag(handle)?'T':'F'));
  printf("box vectors: [%10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f], [%10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f], [%10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f]\n",
    fcs_get_box_a(handle)[0], fcs_get_box_a(handle)[1], fcs_get_box_a(handle)[2],
    fcs_get_box_b(handle)[0], fcs_get_box_b(handle)[1], fcs_get_box_b(handle)[2],
    fcs_get_box_c(handle)[0], fcs_get_box_c(handle)[1], fcs_get_box_c(handle)[2]);
  printf("box origin: [%10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f %10.4" FCS_LMOD_FLOAT "f]\n",
    fcs_get_box_origin(handle)[0], fcs_get_box_origin(handle)[1], fcs_get_box_origin(handle)[2]);
  printf("periodicity: %c %c %c\n", ((fcs_get_periodicity(handle)[0] == 1)?'T':'F'), ((fcs_get_periodicity(handle)[1] == 1)?'T':'F'),((fcs_get_periodicity(handle)[2] == 1)?'T':'F'));
  printf("total particles: %" FCS_LMOD_INT "d\n", fcs_get_total_particles(handle));
  printf("solver specific data:\n");

  if (handle->print_parameters)
  {
    result = handle->print_parameters(handle);
    if (result != FCS_RESULT_SUCCESS) fcs_result_print_result(result);
  }

  result = fcs_common_print_parameters(handle);
  if (result != FCS_RESULT_SUCCESS) fcs_result_print_result(result);

  return FCS_RESULT_SUCCESS;
}
Ejemplo n.º 4
0
/* internal p3m-specific tuning function */
FCSResult fcs_mmm2d_tune(FCS handle,
		       fcs_int local_particles,
		       fcs_float *positions, fcs_float *charges)
{
  FCSResult result;
  
  MMM2D_CHECK_RETURN_RESULT(handle, __func__);
  
  /* Check box periodicity */
  const fcs_int *periodicity = fcs_get_periodicity(handle);
  if (periodicity[0] != 1 ||
      periodicity[1] != 1 ||
      periodicity[2] != 0)
    return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, "mmm2d requires x and y-axis periodic boundaries.");
  
  /* Check box shape */
  ///@TODO: check for rectangular box geometry (any fcs adequate method?)
  const fcs_float *a = fcs_get_box_a(handle);
  const fcs_float *b = fcs_get_box_b(handle);
  const fcs_float *c = fcs_get_box_c(handle);
  
  /*
  if (!fcs_is_orthogonal(a, b, c))
    return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, 
          "p3m requires the box to be orthorhombic.");

  if (!fcs_uses_principal_axes(a, b, c))
    return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, 
          "p3m requires the box vectors to be parallel to the principal axes.");
  */
  
  mmm2d_set_box_a(handle->method_context, a[0]);
  mmm2d_set_box_b(handle->method_context, b[1]);
  mmm2d_set_box_c(handle->method_context, c[2]);
  
  /* Effectively, tune initializes the algorithm */
  result = mmm2d_tune(handle->method_context,
        local_particles,
        positions, charges);
  
  return result;
}
Ejemplo n.º 5
0
/* internal fmm-specific run function */
FCSResult fcs_fmm_run(FCS handle, fcs_int local_particles,
                      fcs_float *positions, fcs_float *charges, 
                      fcs_float *field, fcs_float *potentials)
{
  FCSResult result;

  long long ll_tp;
  long long ll_lp;
  long long ll_absrel;
  long long ll_dip_corr;
  const fcs_int* periodicity;
  long long* ll_periodicity;
  int i;
  fcs_float tolerance_energy;
  fcs_float period_length;
  void* params;
  fcs_int dotune;
  long long r;
  const fcs_float* box_vector;
  void* loadptr = NULL;

  FMM_CHECK_RETURN_RESULT(handle, __func__);

  result = fcs_fmm_check(handle, local_particles);
  CHECK_RESULT_RETURN(result);

  ll_periodicity = (long long*)malloc(3*sizeof(long long));

  ll_tp = (long long)fcs_get_total_particles(handle);
  ll_lp = (long long)local_particles;

  fcs_int absrel;
  fcs_fmm_get_absrel(handle, &absrel);
  ll_absrel = absrel;

  fcs_fmm_get_tolerance_energy(handle, &tolerance_energy);

  fcs_int dip_corr;
  fcs_fmm_get_dipole_correction(handle, &dip_corr);

  ll_dip_corr = dip_corr;

  periodicity = fcs_get_periodicity(handle);
  for (i = 0; i < 3; i++)
    ll_periodicity[i] = (long long)periodicity[i];
  params = fcs_get_method_context(handle);
  box_vector = fcs_get_box_a(handle);
  period_length = fcs_norm(box_vector);

  fcs_fmm_get_internal_tuning( handle, &dotune );
  if (dotune != FCS_FMM_INHOMOGENOUS_SYSTEM && dotune != FCS_FMM_HOMOGENOUS_SYSTEM)
  {
    result = fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, "wrong kind of internal tuning chosen");
    return result;
  }

  long long ll_unroll_limit = handle->fmm_param->limit;
  long long ll_maxdepth = handle->fmm_param->maxdepth;
  long long ll_balance_load = handle->fmm_param->balance;
  long long define_loadvector = handle->fmm_param->define_loadvector;
 
  if (define_loadvector == 1)
  {
    handle->fmm_param->define_loadvector = 0;
    long long ll_loadvectorsize = ll_loadvectorsize = 229074;/*local_particles*4;*/
    fcs_float val = 1e0;
    loadptr = malloc(sizeof(ll_loadvectorsize)*ll_loadvectorsize);
    fmm_cinitload(params,loadptr,ll_loadvectorsize);
    fmm_csetload(params,val);
  }

  int old_fcs_mpi_fmm_sort_front_part = fcs_mpi_fmm_sort_front_part;

  int comm_size;
  MPI_Comm_size(fcs_get_communicator(handle), &comm_size);
  fcs_float max_merge_move = fcs_pow(fcs_norm(fcs_get_box_a(handle)) * fcs_norm(fcs_get_box_b(handle)) * fcs_norm(fcs_get_box_c(handle)) / comm_size, 1.0 / 3.0);

  fcs_float max_particle_move;
  MPI_Allreduce(&handle->fmm_param->max_particle_move, &max_particle_move, 1, FCS_MPI_FLOAT, MPI_MAX, fcs_get_communicator(handle));

  if (max_particle_move >= 0 && max_particle_move < max_merge_move)
  {
/*    fmm_csetpresorted(params, 1);*/
    fcs_mpi_fmm_sort_front_part = 0;
    fcs_mpi_fmm_sort_front_merge_presorted = 1;

  } else
  {
/*    fmm_csetpresorted(params, 0);*/
    fcs_mpi_fmm_sort_front_merge_presorted = 0;
  }

  fcs_fmm_resort_destroy(&handle->fmm_param->fmm_resort);
  if (handle->fmm_param->resort) fcs_fmm_resort_create(&handle->fmm_param->fmm_resort, local_particles, fcs_get_communicator(handle));
  fmm_cinitresort(params, handle->fmm_param->fmm_resort);
  fmm_csetresort(params, (long long) handle->fmm_param->resort);

  fmm_crun(ll_lp,positions,charges,potentials,field,handle->fmm_param->virial,ll_tp,ll_absrel,tolerance_energy,
    ll_dip_corr, ll_periodicity, period_length, dotune, ll_maxdepth,ll_unroll_limit,ll_balance_load,params, &r);

  fcs_mpi_fmm_sort_front_part = old_fcs_mpi_fmm_sort_front_part;

  free(ll_periodicity);
  if (loadptr) free(loadptr);

  if (r == 0)
  {
    result = fcs_result_create(FCS_ERROR_FORTRAN_CALL, __func__, "error in fmm_run (FORTRAN)");
    return result;
  }

  return FCS_RESULT_SUCCESS;
}
Ejemplo n.º 6
0
/* internal fmm-specific tuning function */
FCSResult fcs_fmm_tune(FCS handle, fcs_int local_particles, fcs_float *positions, fcs_float *charges)
{
  FCSResult result;

  fcs_int dotune;
  long long ll_tp;
  long long ll_lp;
  long long ll_absrel;
  long long ll_dip_corr;
  const fcs_int* periodicity;
  long long* ll_periodicity;
  int i;
  fcs_float tolerance_energy;
  fcs_float period_length;
  void* params;
  long long wignersize;
  long long r;
  const fcs_float* box_vector;
  void* loadptr = NULL;

  FMM_CHECK_RETURN_RESULT(handle, __func__);

  result = fcs_fmm_check(handle, local_particles);
  CHECK_RESULT_RETURN(result);

  ll_periodicity = (long long*)malloc(3*sizeof(long long));

  ll_tp = (long long)fcs_get_total_particles(handle);
  ll_lp = (long long)local_particles;
  fcs_int absrel;
  fcs_fmm_get_absrel(handle, &absrel);
  ll_absrel = absrel;
  fcs_fmm_get_tolerance_energy(handle, &tolerance_energy);
  fcs_int dip_corr;
  fcs_fmm_get_dipole_correction(handle, &dip_corr);
  ll_dip_corr = dip_corr;
  periodicity = fcs_get_periodicity(handle);
  for (i = 0; i < 3; i++)
    ll_periodicity[i] = (long long)periodicity[i];
  params = fcs_get_method_context(handle);
  box_vector = fcs_get_box_a(handle);
  period_length = fcs_norm(box_vector);

  long long ll_unroll_limit = handle->fmm_param->limit;
  long long ll_maxdepth = handle->fmm_param->maxdepth;
  long long ll_balance_load = handle->fmm_param->balance;
  long long define_loadvector = handle->fmm_param->define_loadvector;

  fcs_fmm_get_internal_tuning( handle, &dotune );
  if (dotune == FCS_FMM_INHOMOGENOUS_SYSTEM)
  {
    if (define_loadvector == 1)
    {
      handle->fmm_param->define_loadvector = 0;
      long long ll_loadvectorsize = 4*local_particles;
      fcs_float val = 1e0;
      loadptr = malloc(sizeof(ll_loadvectorsize)*ll_loadvectorsize);
      fmm_cinitload(params,loadptr,ll_loadvectorsize);
      fmm_csetload(params,val);
    }

    fmm_ctune(ll_lp,positions,charges,ll_tp,ll_absrel,tolerance_energy,ll_dip_corr,
      ll_periodicity, period_length, ll_maxdepth, ll_unroll_limit, ll_balance_load,params, &wignersize, &r);

  } else if ( dotune == FCS_FMM_HOMOGENOUS_SYSTEM )
  {
    fmm_ctunehomogen(params,&wignersize, &r);

  } else
  {
    result = fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, "wrong kind of internal tuning chosen");
    return result;
  }

  if (handle->fmm_param->wignerptr == NULL || handle->fmm_param->wignersize < wignersize)
  {
    if (handle->fmm_param->wignerptr) free(handle->fmm_param->wignerptr);

    handle->fmm_param->wignersize = wignersize;
    handle->fmm_param->wignerptr = malloc(wignersize);
  }

  fmm_ccomputewigner(handle->fmm_param->wignerptr,params,dotune);

  free(ll_periodicity);
  if (loadptr) free(loadptr);

  if (r == 0)
  {
    result = fcs_result_create(FCS_ERROR_FORTRAN_CALL, __func__, "error in fmm_ctune (FORTRAN)");
    return result;
  }
  
  return FCS_RESULT_SUCCESS;
}
Ejemplo n.º 7
0
FCSResult fcs_fmm_check(FCS handle)
{
  const fcs_float *a,*b,*c;
  const fcs_int *periodicity;
  int i,p;

  fcs_int absrel;
  fcs_fmm_get_absrel(handle, &absrel);
  if (absrel == -1)
    return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: absrel not set");

  fcs_float deltaE;
  fcs_fmm_get_deltaE(handle, &deltaE);
  if (deltaE == -1.0)
    return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: deltaE not set");

  a = fcs_get_box_a(handle);
  b = fcs_get_box_b(handle);
  c = fcs_get_box_c(handle);
  periodicity = fcs_get_periodicity(handle);

  p = 0;
  for (i = 0; i < 3; ++i)
    if (periodicity[i]) p++;

  switch(p)
  {
    case 0:
      return FCS_RESULT_SUCCESS;
    case 1:
      for (i = 0; i < 3; ++i)
        if (periodicity[i]) break;
      switch(i)
      {
        case 0:
          if (!( (fcs_norm(a) >= fcs_norm(b)) && (fcs_norm(a) >= fcs_norm(c)) ))
            return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
              "fmm: longest box vector not in direction of 1D-periodicity direction");


          return FCS_RESULT_SUCCESS;
        case 1:
          if (!( (fcs_norm(b) >= fcs_norm(a)) && (fcs_norm(b) >= fcs_norm(a)) ))
            return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
              "fmm: longest box vector not in direction of 1D-periodicity direction");
          return FCS_RESULT_SUCCESS;
        case 2:
          if (!( (fcs_norm(c) >= fcs_norm(a)) && (fcs_norm(c) >= fcs_norm(b)) ))
            return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
              "fmm: longest box vector not in direction of 1D-periodicity direction");
          return FCS_RESULT_SUCCESS;
      }
    case 2:
      for (i = 0; i < 3; ++i)
        if (!periodicity[i]) break;
      switch(i)
      {
        case 0:
          if (!( (fcs_float_is_equal(fcs_norm(b),fcs_norm(c))) && (fcs_norm(b) >= fcs_norm(a)) ))


            return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
              "fmm: longest box vector not in direction of 2D-periodicity direction");
          return FCS_RESULT_SUCCESS;
        case 1:
          if (!( (fcs_float_is_equal(fcs_norm(a),fcs_norm(c))) && (fcs_norm(a) >= fcs_norm(b)) ))
            return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
              "fmm: longest box vector not in direction of 2D-periodicity direction");
          return FCS_RESULT_SUCCESS;
        case 2:
          if (!( (fcs_float_is_equal(fcs_norm(a),fcs_norm(b))) && (fcs_norm(a) >= fcs_norm(c)) ))
            return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
              "fmm: longest box vector not in direction of 2D-periodicity direction");
          return FCS_RESULT_SUCCESS;
      }
    case 3:
      if (!(fcs_uses_principal_axes(a,b,c))) 
        return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: cannot use a non-cubic system in 3D-periodicity");
      return FCS_RESULT_SUCCESS;
  }

  return FCS_RESULT_SUCCESS;
}
Ejemplo n.º 8
0
/* method to check if fmm parameters are consistent with requirements */
FCSResult fcs_fmm_check(FCS handle, fcs_int local_particles)
{
  const fcs_float *a,*b,*c;
  fcs_float norm[3],period_length;
  const fcs_int *periodicity;
  MPI_Comm comm;
  fcs_int total_particles;
  int comm_size;
  int i,p,ok;

  fcs_int absrel;
  fcs_fmm_get_absrel(handle, &absrel);
  if (absrel == -1)
    return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: absrel not set");

  fcs_float tolerance_energy;
  fcs_fmm_get_tolerance_energy(handle, &tolerance_energy);
  if (tolerance_energy == -1.0)
    return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "fmm: energy tolerance not set");

  comm = fcs_get_communicator(handle);
  MPI_Comm_size(comm, &comm_size);
  total_particles = fcs_get_total_particles(handle);
  if (total_particles < comm_size)
    return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: there have to be at least as much particles as processes");
  
  if (local_particles <= 0)
    return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "fmm: each process has to receive at least one particle");
  
  a = fcs_get_box_a(handle); 
  norm[0] = fcs_norm(a);
  b = fcs_get_box_b(handle);
  norm[1] = fcs_norm(b);
  c = fcs_get_box_c(handle);
  norm[2] = fcs_norm(c);
  periodicity = fcs_get_periodicity(handle);

  p = 0; ok = 1;
  for (i = 0; i < 3; ++i)
    if (periodicity[i]) 
    {
      if (0==p) 
        period_length = norm[i];
      else 
        ok = ok && fcs_float_is_equal( period_length, norm[i] );
      p++;
    }

  if (p && !(fcs_uses_principal_axes(a,b,c))) 
    return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
      "fmm: with periodic boundaries, box must be arranged along principle axes");

  if (p && !ok)
    return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
      "fmm: all periodic directions must have equal length");

  if (p && (p<3)) 
  {
    ok = 1;
    for (i = 0; i < 3; ++i)
      if (!periodicity[i]) 
        ok = ok && (norm[i] <= period_length);
    if (!ok)
      return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, 
        "fmm: axes in non-periodic directions must not be longer than periodic ones");
  }

  return FCS_RESULT_SUCCESS;
}
Ejemplo n.º 9
0
FCSResult fcs_vmg_tune(FCS handle, fcs_int local_particles, fcs_int local_max_particles,
		       fcs_float* positions, fcs_float* charges)
{
  FCSResult result;
  /*
   * Set default parameters if no parameters were specified
   */
  result = fcs_vmg_set_default(handle);
  if (result)
    return result;

  /*
   * Check parameters
   */
  result = fcs_vmg_check(handle);
  if (result)
    return result;

  /*
   * Setup vmg solver
   */
  fcs_int level;
  fcs_int max_iter;
  fcs_int smoothing_steps;
  fcs_int cycle_type;
  fcs_float precision;
  fcs_int near_field_cells;
  fcs_int interpolation_order;
  fcs_int discretization_order;

  result = fcs_vmg_get_max_level(handle, &level);
  if (result)
    return result;

  fcs_int* periodic = fcs_get_periodicity(handle);

  result  = fcs_vmg_get_max_iterations(handle, &max_iter);
  if (result)
    return result;

  result  = fcs_vmg_get_smoothing_steps(handle, &smoothing_steps);
  if (result)
    return result;

  result  = fcs_vmg_get_cycle_type(handle, &cycle_type);
  if (result)
    return result;

  result  = fcs_vmg_get_precision(handle, &precision);
  if (result)
    return result;

  fcs_float *offset = fcs_get_offset(handle);
  fcs_float* box_a = fcs_get_box_a(handle);

  result  = fcs_vmg_get_near_field_cells(handle, &near_field_cells);
  if (result)
    return result;

  result  = fcs_vmg_get_interpolation_order(handle, &interpolation_order);
  if (result)
    return result;

  result  = fcs_vmg_get_discretization_order(handle, &discretization_order);
  if (result)
    return result;

  MPI_Comm comm = fcs_get_communicator(handle);

  VMG_fcs_setup(level, periodic, max_iter, smoothing_steps,
		cycle_type, precision, offset, box_a[0],
		near_field_cells, interpolation_order,
		discretization_order, comm);

  result = fcs_vmg_library_check(handle);
  if (result)
    return result;

  return NULL;
}
Ejemplo n.º 10
0
/* internal pepc-specific run function */
FCSResult fcs_pepc_run(FCS handle, fcs_int local_particles,
		       fcs_float *positions, fcs_float *charges, 
		       fcs_float *field, fcs_float *potentials)
{
  FCSResult result;
  fcs_int pcnt;
  fcs_int nparts_tot;
  fcs_pepc_internal_t *pepc_internal;

  nparts_tot = fcs_get_total_particles(handle);

  pepc_internal = (fcs_pepc_internal_t*) fcs_get_method_context(handle);
  
  if((local_particles != pepc_internal->work_length) || (handle->pepc_param->load_balancing==0)){
    
    if(pepc_internal->work != NULL){
      free(pepc_internal->work);
    }
    
    pepc_internal->work = (fcs_float*)malloc(sizeof(fcs_float)*local_particles);
    pepc_internal->work_length = local_particles;

    for(int pcnt=0; pcnt<pepc_internal->work_length; pcnt++)
      pepc_internal->work[pcnt] = 1.0;
  }
  
  result = fcs_pepc_check(handle);
  CHECK_RESULT_RETURN(result);

  fcs_int max_local_particles = fcs_get_max_local_particles(handle);
  if (local_particles > max_local_particles) max_local_particles = local_particles;

  if (handle->pepc_param->debug_level > 3) {
    printf("*** run pepc kernel\n");
    printf("** local particles:        %" FCS_LMOD_INT "d\n", local_particles);
    printf("** max local particles:    %" FCS_LMOD_INT "d\n", max_local_particles);
    printf("** total particles:        %" FCS_LMOD_INT "d\n", nparts_tot);
    printf("** epsilon:                %" FCS_LMOD_FLOAT "f\n", handle->pepc_param->epsilon);
    printf("** theta:                  %" FCS_LMOD_FLOAT "f\n", handle->pepc_param->theta);
    printf("** npm:                    %" FCS_LMOD_FLOAT "f\n", handle->pepc_param->npm);
    printf("** debug_level:            %" FCS_LMOD_INT "d\n", handle->pepc_param->debug_level);
    printf("** require virial:         %" FCS_LMOD_INT "d\n", handle->pepc_param->require_virial);
    printf("** num walk threads:       %" FCS_LMOD_INT "d\n", handle->pepc_param->num_walk_threads);
    printf("** dipole correction:      %" FCS_LMOD_INT "d\n", handle->pepc_param->dipole_correction);
    printf("** use load balancing:     %" FCS_LMOD_INT "d\n", handle->pepc_param->load_balancing);
    printf("** size int:               %d\n", (int)sizeof(fcs_int));
    printf("** size float:             %d\n", (int)sizeof(fcs_float));
    printf("** debug lattice pointers: %p\n", fcs_get_box_a(handle));
    printf("** debug lattice pointers: %p\n", fcs_get_box_b(handle));
    printf("** debug lattice pointers: %p\n", fcs_get_box_c(handle));

    printf("** debug output lattice in x %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f\n", 
	   fcs_get_box_a(handle)[0], fcs_get_box_a(handle)[1], fcs_get_box_a(handle)[2]);
    printf("** debug output lattice in y %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f\n", 
	   fcs_get_box_b(handle)[0], fcs_get_box_b(handle)[1], fcs_get_box_b(handle)[2]);
    printf("** debug output lattice in z %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f %" FCS_LMOD_FLOAT "f\n", 
	   fcs_get_box_c(handle)[0], fcs_get_box_c(handle)[1], fcs_get_box_c(handle)[2]);
  }

  pepc_scafacos_run(&local_particles, &nparts_tot, positions, charges,
		    field, potentials, pepc_internal->work,
		    ((fcs_pepc_internal_t*)(handle->method_context))->virial,
		    fcs_get_box_a(handle), fcs_get_box_b(handle), fcs_get_box_c(handle),
		    fcs_get_periodicity(handle), &handle->pepc_param->dipole_correction,
		    &handle->pepc_param->epsilon, &handle->pepc_param->theta, &handle->pepc_param->debug_level, &handle->pepc_param->num_walk_threads, &handle->pepc_param->npm);

  if (handle->pepc_param->debug_level > 3)
  {
    printf("virial(0,0) %12.4e\n", ((fcs_pepc_internal_t*)(handle->method_context))->virial[0]);

    for(pcnt=0; pcnt<local_particles; pcnt++)
      printf("** e-field dump, particle %" FCS_LMOD_INT "d, (ex,ey,ez): %" FCS_LMOD_FLOAT "f, %" FCS_LMOD_FLOAT "f, %" FCS_LMOD_FLOAT "f\n", pcnt, field[pcnt+0], field[pcnt+1], field[pcnt+2]);
  }

  return FCS_RESULT_SUCCESS;
}