void colvar::cvc::debug_gradients(cvm::atom_group *group) { // this function should work for any scalar variable: // the only difference will be the name of the atom group (here, "group") // NOTE: this assumes that groups for this cvc are non-overlapping, // since atom coordinates are modified only within the current group if (group->b_dummy) return; cvm::rotation const rot_0 = group->rot; cvm::rotation const rot_inv = group->rot.inverse(); cvm::real x_0 = x.real_value; if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_0 = x[0]; // cvm::log("gradients = "+cvm::to_str (gradients)+"\n"); cvm::atom_group *group_for_fit = group->ref_pos_group ? group->ref_pos_group : group; cvm::atom_pos fit_gradient_sum, gradient_sum; // print the values of the fit gradients if (group->b_rotate || group->b_center) { if (group->b_fit_gradients) { size_t j; // fit_gradients are in the simulation frame: we should print them in the rotated frame cvm::log("Fit gradients:\n"); for (j = 0; j < group_for_fit->fit_gradients.size(); j++) { cvm::log((group->ref_pos_group ? std::string("refPosGroup") : group->key) + "[" + cvm::to_str(j) + "] = " + (group->b_rotate ? cvm::to_str(rot_0.rotate(group_for_fit->fit_gradients[j])) : cvm::to_str(group_for_fit->fit_gradients[j]))); } } } // debug the gradients for (size_t ia = 0; ia < group->size(); ia++) { // tests are best conducted in the unrotated (simulation) frame cvm::rvector const atom_grad = (group->b_rotate ? rot_inv.rotate((*group)[ia].grad) : (*group)[ia].grad); gradient_sum += atom_grad; for (size_t id = 0; id < 3; id++) { // (re)read original positions group->read_positions(); // change one coordinate (*group)[ia].pos[id] += cvm::debug_gradients_step_size; group->calc_required_properties(); calc_value(); cvm::real x_1 = x.real_value; if ((x.type() == colvarvalue::type_vector) && (x.size() == 1)) x_1 = x[0]; cvm::log("Atom "+cvm::to_str(ia)+", component "+cvm::to_str(id)+":\n"); cvm::log("dx(actual) = "+cvm::to_str(x_1 - x_0, 21, 14)+"\n"); cvm::real const dx_pred = (group->fit_gradients.size()) ? (cvm::debug_gradients_step_size * (atom_grad[id] + group->fit_gradients[ia][id])) : (cvm::debug_gradients_step_size * atom_grad[id]); cvm::log("dx(interp) = "+cvm::to_str(dx_pred, 21, 14)+"\n"); cvm::log("|dx(actual) - dx(interp)|/|dx(actual)| = "+ cvm::to_str(std::fabs(x_1 - x_0 - dx_pred) / std::fabs(x_1 - x_0), 12, 5)+"\n"); } } if ((group->b_fit_gradients) && (group->ref_pos_group != NULL)) { cvm::atom_group *ref_group = group->ref_pos_group; group->read_positions(); group->calc_required_properties(); for (size_t ia = 0; ia < ref_group->size(); ia++) { // fit gradients are in the unrotated (simulation) frame cvm::rvector const atom_grad = ref_group->fit_gradients[ia]; fit_gradient_sum += atom_grad; for (size_t id = 0; id < 3; id++) { // (re)read original positions group->read_positions(); ref_group->read_positions(); // change one coordinate (*ref_group)[ia].pos[id] += cvm::debug_gradients_step_size; group->calc_required_properties(); calc_value(); cvm::real const x_1 = x.real_value; cvm::log("refPosGroup atom "+cvm::to_str(ia)+", component "+cvm::to_str (id)+":\n"); cvm::log("dx(actual) = "+cvm::to_str (x_1 - x_0, 21, 14)+"\n"); cvm::real const dx_pred = cvm::debug_gradients_step_size * atom_grad[id]; cvm::log("dx(interp) = "+cvm::to_str (dx_pred, 21, 14)+"\n"); cvm::log ("|dx(actual) - dx(interp)|/|dx(actual)| = "+ cvm::to_str(std::fabs (x_1 - x_0 - dx_pred) / std::fabs (x_1 - x_0), 12, 5)+ ".\n"); } } } cvm::log("Gradient sum: " + cvm::to_str(gradient_sum) + " Fit gradient sum: " + cvm::to_str(fit_gradient_sum) + " Total " + cvm::to_str(gradient_sum + fit_gradient_sum)); return; }
void colvar::cvc::debug_gradients (cvm::atom_group &group) { // this function should work for any scalar variable: // the only difference will be the name of the atom group (here, "group") if (group.b_dummy) return; cvm::rotation const rot_0 = group.rot; cvm::rotation const rot_inv = group.rot.inverse(); cvm::real const x_0 = x.real_value; // cvm::log ("gradients = "+cvm::to_str (gradients)+"\n"); // it only makes sense to debug the fit gradients // when the fitting group is the same as this group if (group.b_rotate || group.b_center) if (group.b_fit_gradients && (group.ref_pos_group == NULL)) { group.calc_fit_gradients(); if (group.b_rotate) { // fit_gradients are in the original frame, we should print them in the rotated frame for (size_t j = 0; j < group.fit_gradients.size(); j++) { group.fit_gradients[j] = rot_0.rotate (group.fit_gradients[j]); } } cvm::log ("fit_gradients = "+cvm::to_str (group.fit_gradients)+"\n"); if (group.b_rotate) { for (size_t j = 0; j < group.fit_gradients.size(); j++) { group.fit_gradients[j] = rot_inv.rotate (group.fit_gradients[j]); } } } for (size_t ia = 0; ia < group.size(); ia++) { // tests are best conducted in the unrotated (simulation) frame cvm::rvector const atom_grad = group.b_rotate ? rot_inv.rotate (group[ia].grad) : group[ia].grad; for (size_t id = 0; id < 3; id++) { // (re)read original positions group.read_positions(); // change one coordinate group[ia].pos[id] += cvm::debug_gradients_step_size; // (re)do the fit (if defined) if (group.b_center || group.b_rotate) { group.calc_apply_roto_translation(); } calc_value(); cvm::real const x_1 = x.real_value; cvm::log ("Atom "+cvm::to_str (ia)+", component "+cvm::to_str (id)+":\n"); cvm::log ("dx(actual) = "+cvm::to_str (x_1 - x_0, 21, 14)+"\n"); //cvm::real const dx_pred = (group.fit_gradients.size() && (group.ref_pos_group == NULL)) ? cvm::real const dx_pred = (group.fit_gradients.size()) ? (cvm::debug_gradients_step_size * (atom_grad[id] + group.fit_gradients[ia][id])) : (cvm::debug_gradients_step_size * atom_grad[id]); cvm::log ("dx(interp) = "+cvm::to_str (dx_pred, 21, 14)+"\n"); cvm::log ("|dx(actual) - dx(interp)|/|dx(actual)| = "+ cvm::to_str (std::fabs (x_1 - x_0 - dx_pred) / std::fabs (x_1 - x_0), 12, 5)+"\n"); } } /* * The code below is WIP */ // if (group.ref_pos_group != NULL) { // cvm::atom_group &ref = *group.ref_pos_group; // group.calc_fit_gradients(); // // for (size_t ia = 0; ia < ref.size(); ia++) { // // for (size_t id = 0; id < 3; id++) { // // (re)read original positions // group.read_positions(); // ref.read_positions(); // // change one coordinate // ref[ia].pos[id] += cvm::debug_gradients_step_size; // group.calc_apply_roto_translation(); // calc_value(); // cvm::real const x_1 = x.real_value; // cvm::log ("refPosGroup atom "+cvm::to_str (ia)+", component "+cvm::to_str (id)+":\n"); // cvm::log ("dx(actual) = "+cvm::to_str (x_1 - x_0, // 21, 14)+"\n"); // //cvm::real const dx_pred = (group.fit_gradients.size() && (group.ref_pos_group == NULL)) ? // // cvm::real const dx_pred = (group.fit_gradients.size()) ? // // (cvm::debug_gradients_step_size * (atom_grad[id] + group.fit_gradients[ia][id])) : // // (cvm::debug_gradients_step_size * atom_grad[id]); // cvm::real const dx_pred = cvm::debug_gradients_step_size * ref.fit_gradients[ia][id]; // cvm::log ("dx(interp) = "+cvm::to_str (dx_pred, // 21, 14)+"\n"); // cvm::log ("|dx(actual) - dx(interp)|/|dx(actual)| = "+ // cvm::to_str (std::fabs (x_1 - x_0 - dx_pred) / // std::fabs (x_1 - x_0), // 12, 5)+ // ".\n"); // } // } // } return; }