/** * run the solver method */ FCSResult fcs_run(FCS handle, fcs_int local_particles, fcs_float *positions, fcs_float *charges, fcs_float *field, fcs_float *potentials) { const char *fnc_name = "fcs_run"; FCSResult result; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (local_particles < 0) return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, fnc_name, "number of local particles must be non negative"); if (fcs_get_values_changed(handle)) { result = fcs_tune(handle, local_particles, positions, charges); if (result != FCS_RESULT_SUCCESS) return result; } if (!fcs_init_check(handle) || !fcs_run_check(handle)) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, fnc_name, "not all needed data has been inserted into the given handle"); if (handle->run == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, fnc_name, "Running solver method '%s' not implemented", fcs_get_method_name(handle)); return handle->run(handle, local_particles, positions, charges, field, potentials); }
/** * 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; }
/** * return the user-defined cutoff radius for the near-field */ FCSResult fcs_get_r_cut(FCS handle, fcs_float *r_cut) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (handle->get_r_cut == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, __func__, "Returning a user-defined cutoff radius for the near-field not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->get_r_cut(handle, r_cut); }
/** * set the error tolerance of the FCS solver */ FCSResult fcs_set_tolerance(FCS handle, fcs_int tolerance_type, fcs_float tolerance) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (handle->set_tolerance == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, __func__, "Setting tolerance not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->set_tolerance(handle, tolerance_type, tolerance); }
/** * sort additional byte particle data */ FCSResult fcs_resort_bytes(FCS handle, void *src, void *dst, fcs_int n) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (handle->resort_bytes == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "resorting not supported"); return handle->resort_bytes(handle, src, dst, n, fcs_get_communicator(handle)); }
/** * return the new local number of particles */ FCSResult fcs_get_resort_particles(FCS handle, fcs_int *resort_particles) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (handle->get_resort_particles == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "resorting not supported"); return handle->get_resort_particles(handle, resort_particles); }
/** * set whether resort support is requested */ FCSResult fcs_set_resort(FCS handle, fcs_int resort) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (handle->set_resort == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "resorting not supported"); return handle->set_resort(handle, resort); }
/** * sort additional float particle data */ FCSResult fcs_resort_floats(FCS handle, fcs_float *src, fcs_float *dst, fcs_int n) { const char* fnc_name = "fcs_resort_floats"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (handle->resort_floats == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, fnc_name, "resorting not supported"); return handle->resort_floats(handle, src, dst, n, fcs_get_communicator(handle)); }
/** * set whether resort support is requested */ FCSResult fcs_set_resort(FCS handle, fcs_int resort) { const char *fnc_name = "fcs_set_resort"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (handle->set_resort == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, fnc_name, "resorting not supported"); return handle->set_resort(handle, resort); }
/** * disable a user-defined cutoff radius for the near-field */ FCSResult fcs_unset_r_cut(FCS handle) { const char *fnc_name = "fcs_unset_r_cut"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (handle->unset_r_cut == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, fnc_name, "Disabling a user-defined cutoff radius for the near-field not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->unset_r_cut(handle); }
/** * return whether resort support is available */ FCSResult fcs_get_resort_availability(FCS handle, fcs_int *availability) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); *availability = 0; if (handle->get_resort_availability == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "resorting not supported"); return handle->get_resort_availability(handle, availability); }
/** * set the maximum distance the particles have moved since the call of ::fcs_run */ FCSResult fcs_set_max_particle_move(FCS handle, fcs_float max_particle_move) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); /* if (handle->set_max_particle_move == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, __func__, "max. particle move not supported");*/ if (handle->set_max_particle_move == NULL) return FCS_RESULT_SUCCESS; return handle->set_max_particle_move(handle, max_particle_move); }
/** * return the new local number of particles */ FCSResult fcs_get_resort_particles(FCS handle, fcs_int *resort_particles) { const char *fnc_name = "fcs_get_resort_particles"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (handle->get_resort_particles == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, fnc_name, "resorting not supported"); return handle->get_resort_particles(handle, resort_particles); }
/** * return the comuputed virial */ FCSResult fcs_get_virial(FCS handle, fcs_float *virial) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (virial == NULL) return fcs_result_create(FCS_ERROR_NULL_ARGUMENT, __func__, "null pointer supplied as argument"); if (handle->get_virial == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, __func__, "Returning the computed virial not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->get_virial(handle, virial); }
/** * return the error tolerance of the FCS solver */ FCSResult fcs_get_tolerance(FCS handle, fcs_int *tolerance_type, fcs_float *tolerance) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); *tolerance_type = FCS_TOLERANCE_TYPE_UNDEFINED; *tolerance = -1.0; if (handle->get_tolerance == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, __func__, "Return tolerance not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->get_tolerance(handle, tolerance_type, tolerance); }
/** * set whether the virial should be computed */ FCSResult fcs_set_compute_virial(FCS handle, fcs_int compute_virial) { CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (compute_virial != 0 && compute_virial != 1) return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, "parameter compute_virial must be 0 or 1"); if (handle->set_compute_virial == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, __func__, "Setting whether the virial should be computed not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->set_compute_virial(handle, compute_virial); }
/** * set the maximum distance the particles have moved since the call of ::fcs_run */ FCSResult fcs_set_max_particle_move(FCS handle, fcs_float max_particle_move) { const char *fnc_name = "fcs_set_max_particle_move"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); /* if (handle->set_max_particle_move == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, fnc_name, "max. particle move not supported");*/ if (handle->set_max_particle_move == NULL) return FCS_SUCCESS; return handle->set_max_particle_move(handle, max_particle_move); }
/** * return whether resort support is available */ FCSResult fcs_get_resort_availability(FCS handle, fcs_int *availability) { const char *fnc_name = "fcs_get_resort_availability"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); *availability = 0; if (handle->get_resort_availability == NULL) return fcs_result_create(FCS_ERROR_INCOMPATIBLE_METHOD, fnc_name, "resorting not supported"); return handle->get_resort_availability(handle, availability); }
/** * return whether the virial should be computed */ FCSResult fcs_get_compute_virial(FCS handle, fcs_int *compute_virial) { const char *fnc_name = "fcs_get_compute_virial"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (compute_virial == NULL) return fcs_result_create(FCS_ERROR_NULL_ARGUMENT, fnc_name, "null pointer supplied as argument"); if (handle->get_compute_virial == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, fnc_name, "Returning whether the virial should be computed not implemented for solver method '%s'", fcs_get_method_name(handle)); return handle->get_compute_virial(handle, compute_virial); }
/** * destroy an FCS solver */ FCSResult fcs_destroy(FCS handle) { FCSResult result; if (handle == FCS_NULL) return FCS_RESULT_SUCCESS; if (handle->destroy) { result = handle->destroy(handle); if (result != FCS_RESULT_SUCCESS) return result; } free(handle); return FCS_RESULT_SUCCESS; }
/** * run the solver method */ FCSResult fcs_run(FCS handle, fcs_int local_particles, fcs_float *positions, fcs_float *charges, fcs_float *field, fcs_float *potentials) { FCSResult result; CHECK_HANDLE_RETURN_RESULT(handle, __func__); if (local_particles < 0) return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, __func__, "number of local particles must be non negative"); if (fcs_get_values_changed(handle)) { result = fcs_tune(handle, local_particles, positions, charges); if (result != FCS_RESULT_SUCCESS) return result; } if (!fcs_init_check(handle) || !fcs_run_check(handle)) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, __func__, "not all needed data has been inserted into the given handle"); if (handle->run == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, __func__, "Running solver method '%s' not implemented", fcs_get_method_name(handle)); fcs_float original_box_origin[3] = { handle->box_origin[0], handle->box_origin[1], handle->box_origin[2] }; if (handle->shift_positions) { fcs_shift_positions(local_particles, positions, original_box_origin); handle->box_origin[0] = handle->box_origin[1] = handle->box_origin[2] = 0; } result = handle->run(handle, local_particles, positions, charges, field, potentials); if (handle->shift_positions) { fcs_unshift_positions(local_particles, positions, original_box_origin); handle->box_origin[0] = original_box_origin[0]; handle->box_origin[1] = original_box_origin[1]; handle->box_origin[2] = original_box_origin[2]; } return result; }
/** * tune method specific parameters depending on the particles */ FCSResult fcs_tune(FCS handle, fcs_int local_particles, fcs_float *positions, fcs_float *charges) { const char *fnc_name = "fcs_tune"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); if (local_particles < 0) return fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, fnc_name, "number of local particles must be non negative"); if (!fcs_init_check(handle) || !fcs_tune_check(handle)) return fcs_result_create(FCS_ERROR_MISSING_ELEMENT, fnc_name, "not all needed data has been inserted into the given handle"); fcs_set_values_changed(handle, 0); if (handle->tune == NULL) return fcs_result_create(FCS_ERROR_NOT_IMPLEMENTED, fnc_name, "Tuning solver method '%s' not implemented", fcs_get_method_name(handle)); return handle->tune(handle, local_particles, positions, charges); }
/** * set the parameters of the FCS solver based on a parameter string */ FCSResult fcs_set_parameters(FCS handle, const char *parameters, fcs_bool continue_on_errors) { const char *fnc_name = "fcs_set_parameters"; CHECK_HANDLE_RETURN_RESULT(handle, fnc_name); FCSResult result = FCS_RESULT_SUCCESS; char *cur; char *params, *param; fcs_int params_strlen, matched; params_strlen = strlen(parameters) + 1; params = malloc(params_strlen * sizeof(char)); strncpy(params, parameters, params_strlen); cur = params; while (cur) { param = cur; cur = strchr(cur, ','); if (cur) { *cur = 0; ++cur; } /* printf("param: %s\n", param); printf("cur: %s\n", cur);*/ FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("box_a", set_box_a, FCS_PARSE_SEQ(fcs_float, 3)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("box_b", set_box_b, FCS_PARSE_SEQ(fcs_float, 3)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("box_c", set_box_c, FCS_PARSE_SEQ(fcs_float, 3)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("offset", set_box_origin, FCS_PARSE_SEQ(fcs_float, 3)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("periodicity", set_periodicity, FCS_PARSE_SEQ(fcs_int, 3)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("near_field_flag", set_near_field_flag, FCS_PARSE_VAL(fcs_int)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("total_particles", set_total_particles, FCS_PARSE_VAL(fcs_int)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("r_cut", set_r_cut, FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC1_GOTO_NEXT("require_virial", set_compute_virial, FCS_PARSE_VAL(fcs_int)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("", set_tolerance, FCS_PARSE_VAL(fcs_int), FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("tolerance_energy", set_tolerance, FCS_PARSE_CONST(fcs_int, FCS_TOLERANCE_TYPE_ENERGY), FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("tolerance_energy_rel", set_tolerance, FCS_PARSE_CONST(fcs_int, FCS_TOLERANCE_TYPE_ENERGY_REL), FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("tolerance_potential", set_tolerance, FCS_PARSE_CONST(fcs_int, FCS_TOLERANCE_TYPE_POTENTIAL), FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("tolerance_potential_rel", set_tolerance, FCS_PARSE_CONST(fcs_int, FCS_TOLERANCE_TYPE_POTENTIAL_REL), FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("tolerance_field", set_tolerance, FCS_PARSE_CONST(fcs_int, FCS_TOLERANCE_TYPE_FIELD), FCS_PARSE_VAL(fcs_float)); FCS_PARSE_IF_PARAM_THEN_FUNC2_GOTO_NEXT("tolerance_field_rel", set_tolerance, FCS_PARSE_CONST(fcs_int, FCS_TOLERANCE_TYPE_FIELD_REL), FCS_PARSE_VAL(fcs_float)); if (handle->set_parameter) { result = handle->set_parameter(handle, continue_on_errors, ¶m, &cur, &matched); if (matched) goto next_param; } result = fcs_common_set_parameter(handle, continue_on_errors, ¶m, &cur, &matched); if (matched) goto next_param; if (result == FCS_RESULT_SUCCESS) result = fcs_result_create(FCS_ERROR_WRONG_ARGUMENT, fnc_name, "interface (parser): error in parameter string at '%s'!", param); if (FCS_IS_FALSE(continue_on_errors)) break; next_param: ; } free(params); return result; }