// calculates and adds its forces to the current forces of the force field
	void MMFF94OutOfPlaneBend::updateForces()
	{
		const double FC = K0 * 2. * RADIAN_TO_DEGREE * RADIAN_TO_DEGREE;
		bool us = getForceField()->getUseSelection();

		//////////////////////////////////////////////////////////////////
		// ids of the non-central atoms for the three runs per out of plane bend:
		vector<vector<Position> > atom_ids;
		// Atom i:
		vector<Position> temp;
		temp.push_back(0);
		temp.push_back(0);
		temp.push_back(1);
		atom_ids.push_back(temp);

		// Atom k:
		temp.clear();
		temp.push_back(1);
		temp.push_back(2);
		temp.push_back(2);
		atom_ids.push_back(temp);

		// Atom l:
		temp.clear();
		temp.push_back(2);
		temp.push_back(1);
		temp.push_back(0);
		atom_ids.push_back(temp);

		////////////////////////////////////////////////////////////////////////
		// all calculations below have to be performed at double precision
		// otherwise the results are far off, especially for small wilson angles
		//
		// temp variables:
		double length;
		TVector3<double> delta;

		// the three atoms bound to the central atom (for the actual plane bend)
		vector<Atom*> partners(3);
		// lenght of the vectors from the central atom to outer atoms:
		vector<double> lengths(3);
		// normalized bond vectors from central atom to outer atoms:
		vector<TVector3<double> > nbv(3);
		
		// index of the individual atoms in partners and nbv:
		Position pi, pk, pl;

		// normal vectors of the three planes:
		TVector3<double> an, bn, cn;

		for (Position t = 0; t < bends_.size(); t++)
		{
			// the current bend
			const OutOfPlaneBend& bend = bends_[t];
			Atom& ta1 = *bend.i->ptr;
			Atom& ta2 = *bend.j->ptr;
			Atom& ta3 = *bend.k->ptr;
			Atom& ta4 = *bend.l->ptr;

			// if using selection and no atom is selected: ignore this bend:
			if (us && !ta1.isSelected() &&
								!ta2.isSelected() &&
								!ta3.isSelected() &&
								!ta4.isSelected())
			{
				continue;
			}

			// non central atoms for this bend:
			partners[0] = &ta1;
			partners[1] = &ta3;
			partners[2] = &ta4;
			Atom& center_atom = ta2;

			// abort for this bend if two atoms have the same position:
			bool error = false;

			// calculate normalized bond vectors from central atom to outer atoms:
			for (Position p = 0; p < 3; p++)
			{
				// transformation from single to double precision:
				delta.x = partners[p]->getPosition().x - center_atom.getPosition().x;
				delta.y = partners[p]->getPosition().y - center_atom.getPosition().y;
				delta.z = partners[p]->getPosition().z - center_atom.getPosition().z;
				length = delta.getLength();
				if (Maths::isZero(length))
				{
					error = true;
					break;
				}

				// normalize the bond vector:
				delta /= length;
				// store the normalized bond vector:
				nbv[p] = delta;
				// store length of this bond:
				lengths[p] = length;
			}

			// abort if any bond lenght equals zero
			if (error) continue;

			// three runs per OOP:
			for (Position run = 0; run < 3; run++)
			{
				// position of the individual atoms in partners[] and nbv[]
				pi = atom_ids[0][run];
				pk = atom_ids[1][run];
				pl = atom_ids[2][run];

				Atom& i = *partners[pi];
				Atom& k = *partners[pk];
				Atom& l = *partners[pl];

				// normalized vectors from central atom to outer atoms:
				const TVector3<double>& ji = nbv[pi];
				const TVector3<double>& jk = nbv[pk];
				const TVector3<double>& jl = nbv[pl];

				const double& length_ji = lengths[pi];
				const double& length_jk = lengths[pk];
				const double& length_jl = lengths[pl];

				// the normal vectors of the three planes:
				an = ji % jk;
				bn = jk % jl;
				cn = jl % ji;

				// Bond angle ji to jk
				const double cos_theta = ji * jk;
				const double theta = acos(cos_theta);
				// If theta equals 180 degree or 0 degree
				if (Maths::isZero(theta) ||
						Maths::isZero(fabs(theta - Constants::PI)))
				{
					continue;
				}
				
				const double sin_theta = sin(theta);
				const double sin_dl = an * jl / sin_theta;

				// the wilson angle:
				const double dl = asin(sin_dl);

				// In case: wilson angle equals 0 or 180 degree: do nothing
				if (Maths::isZero(dl) ||
						Maths::isZero(fabs(dl - Constants::PI)))
				{
					continue;
				}
				

				const double cos_dl = cos(dl);

				// if wilson angle equal 90 degree: abort
				if (cos_dl < 0.0001)
				{
					continue;
				}

				// scaling factor for all forces:
				// wilson K0 * this_bend_constant * wilson_angle * DEGREE_TO_RADIAN * DEGREE_TO_RADIAN
				double c1 = -dl * FC * bend.k_oop * FORCES_FACTOR * Constants::JOULE_PER_CAL;

				double tmp = cos_dl / c1;

			/*	
			Log.precision(30);
      Log.error() << "bond   " << theta            << std::endl;
      Log.error() << "wilson " << dl            << std::endl;
			Log.error() << "tan_dl " << tan_dl            << std::endl;
      Log.error() << "cdst   " << cdst            << std::endl;
      Log.error() << "tdst   "  << tdst           << std::endl;
      Log.error() << "c1     " << c1            << std::endl;
      Log.error() << "abc "   << an << bn << cn << std::endl << std::endl << std::endl << std::endl;
			*/

				const TVector3<double> d_l = ((an / sin_theta - jl * sin_dl) / length_jl) / tmp;
				const TVector3<double> d_i = (((bn + (((-ji + jk * cos_theta) * sin_dl) / sin_theta)) / length_ji) / tmp) / sin_theta;
				const TVector3<double> d_k = (((cn + (((-jk + ji * cos_theta) * sin_dl) / sin_theta)) / length_jk) / tmp) / sin_theta;

 				if (!us || i.isSelected()) AddDV3_(i.getForce(), d_i);
 				if (!us || k.isSelected()) AddDV3_(k.getForce(), d_k);
 				if (!us || l.isSelected()) AddDV3_(l.getForce(), d_l);
 				if (!us || center_atom.isSelected()) AddDV3_(center_atom.getForce(), -(d_i + d_k + d_l));

  #ifdef BALL_MMFF94_TEST
			 getForceField()->error() << std::endl
																<< i.getName() << " " << d_i << std::endl
																<< center_atom.getName() << " " << -(d_i  +d_k + d_l) << std::endl
																<< k.getName() << " " << d_k << std::endl
																<< l.getName() << " " << d_l << std::endl;
   #endif
			}
		}
	}