// -----------------------------------------------------------------------------
// Calculate contact forces and torques for all contact pairs.
// -----------------------------------------------------------------------------
void
ChLcpSolverParallelDEM::host_CalcContactForces(
    custom_vector<int>&    ext_body_id,
    custom_vector<real3>&  ext_body_force,
    custom_vector<real3>&  ext_body_torque)
{
#pragma omp parallel for
  for (int index = 0; index < data_container->num_contacts; index++) {
    function_CalcContactForces(
      index,
      data_container->step_size,
      data_container->host_data.pos_data.data(),
      data_container->host_data.rot_data.data(),
      data_container->host_data.vel_data.data(),
      data_container->host_data.omg_data.data(),
      data_container->host_data.elastic_moduli.data(),
      data_container->host_data.mu.data(),
      data_container->host_data.alpha.data(),
      data_container->host_data.cr.data(),
      data_container->host_data.cohesion_data.data(),
      data_container->host_data.bids_rigid_rigid.data(),
      data_container->host_data.cpta_rigid_rigid.data(),
      data_container->host_data.cptb_rigid_rigid.data(),
      data_container->host_data.norm_rigid_rigid.data(),
      data_container->host_data.dpth_rigid_rigid.data(),
      data_container->host_data.erad_rigid_rigid.data(),
      ext_body_id.data(),
      ext_body_force.data(),
      ext_body_torque.data());
  }
}
void ChSolverParallel::ShurProduct(
                                   custom_vector<real> &x,
                                   custom_vector<real> & output) {

   data_container->system_timer.start("ChSolverParallel_shurA");
   shurA(x.data());
   data_container->system_timer.stop("ChSolverParallel_shurA");

   data_container->system_timer.start("ChSolverParallel_shurB");
   shurB(x.data(), output.data());
   data_container->system_timer.stop("ChSolverParallel_shurB");

}
void ChSolverParallel::UpdatePosition(
custom_vector<real> &x) {

   if (rigid_rigid->solve_sliding == true || rigid_rigid->solve_spinning == true) {
      return;
   }
   shurA(x.data());

   data_container->host_data.vel_new_data = data_container->host_data.vel_data + data_container->host_data.QXYZ_data;
   data_container->host_data.omg_new_data + data_container->host_data.omg_data + data_container->host_data.QUVW_data;

#pragma omp parallel for
   for (int i = 0; i < data_container->num_bodies; i++) {

      data_container->host_data.pos_new_data[i] = data_container->host_data.pos_data[i] + data_container->host_data.vel_new_data[i] * step_size;
      //real3 dp = data_container->host_data.pos_new_data[i]-data_container->host_data.pos_data[i];
      //cout<<dp<<endl;
      real4 moldrot = data_container->host_data.rot_data[i];
      real3 newwel = data_container->host_data.omg_new_data[i];

      M33 A = AMat(moldrot);
      real3 newwel_abs = MatMult(A, newwel);
      real mangle = length(newwel_abs) * step_size;
      newwel_abs = normalize(newwel_abs);
      real4 mdeltarot = Q_from_AngAxis(mangle, newwel_abs);
      real4 mnewrot = mdeltarot % moldrot;
      data_container->host_data.rot_new_data[i] = mnewrot;
   }
}
// -----------------------------------------------------------------------------
// Calculate contact forces and torques for all contact pairs.
// -----------------------------------------------------------------------------
void ChLcpSolverParallelDEM::host_CalcContactForces(custom_vector<int>& ext_body_id,
                                                    custom_vector<real3>& ext_body_force,
                                                    custom_vector<real3>& ext_body_torque,
                                                    custom_vector<int2>& shape_pairs,
                                                    custom_vector<bool>& shear_touch) {
#pragma omp parallel for
  for (int index = 0; index < data_manager->num_rigid_contacts; index++) {
    function_CalcContactForces(index,
                               data_manager->settings.solver.contact_force_model,
                               data_manager->settings.solver.tangential_displ_mode,
                               data_manager->settings.solver.use_material_properties,
                               data_manager->settings.solver.characteristic_vel,
                               data_manager->settings.solver.min_slip_vel,
                               data_manager->settings.step_size,
                               data_manager->host_data.mass_rigid.data(),
                               data_manager->host_data.pos_rigid.data(),
                               data_manager->host_data.rot_rigid.data(),
                               data_manager->host_data.v.data(),
                               data_manager->host_data.elastic_moduli.data(),
                               data_manager->host_data.cr.data(),
                               data_manager->host_data.dem_coeffs.data(),
                               data_manager->host_data.mu.data(),
                               data_manager->host_data.cohesion_data.data(),
                               data_manager->host_data.bids_rigid_rigid.data(),
                               shape_pairs.data(),
                               data_manager->host_data.cpta_rigid_rigid.data(),
                               data_manager->host_data.cptb_rigid_rigid.data(),
                               data_manager->host_data.norm_rigid_rigid.data(),
                               data_manager->host_data.dpth_rigid_rigid.data(),
                               data_manager->host_data.erad_rigid_rigid.data(),
                               data_manager->host_data.shear_neigh.data(),
                               shear_touch.data(),
                               data_manager->host_data.shear_disp.data(),
                               ext_body_id.data(),
                               ext_body_force.data(),
                               ext_body_torque.data());
  }
}