Я пытаюсь написать программу молекулярной динамики, и я подумал, что Boost.Units был логичным выбором для переменных, и я также решил, что Boost.Multiprecision предлагает лучший вариант, чем double
или же long double
в отношении ошибок округления. Комбинация из двух кажется довольно простой, пока я не попытаюсь использовать константу, а затем она сломается.
#include <boost/multiprecision/gmp.hpp>
#include <boost/units/io.hpp>
#include <boost/units/pow.hpp>
#include <boost/units/quantity.hpp>
#include <boost/units/systems/si.hpp>
#include <boost/units/systems/si/codata/physico-chemical_constants.hpp>
namespace units = boost::units;
namespace si = boost::si;
namespace mp = boost::multiprecision;
units::quantity<si::mass, mp::mpf_float_50> mass = 1.0 * si::kilogram;
units::quantity<si::temperature, mp::mpf_float_50> temperature = 300. * si::kelvin;
auto k_B = si::constants::codata::k_B; // Boltzmann constant
units::quantity<si::velocity, mp::mpf_float_50> velocity = units::root<2>(temperature * k_B / mass);
std::cout << velocity << std::endl;
Выход будет 1 M S^-1
, Если я использую long double
вместо mp::mpf_float_50
то результат 2.87818e-11 m s^-1
, Я знаю, что проблема нравится в преобразовании между константой и другими данными, потому что константа по умолчанию double
, Я думал о создании своей собственной постоянной Больцмана, но я предпочитаю использовать предопределенное значение, если это возможно.
Поэтому мой вопрос, как мне использовать Boost.Multiprecision, когда у меня есть предопределенные константы из Boost.Units? Если я должен уступить использованию double
или же long double
, тогда я буду, но я подозреваю, что существует способ конвертировать или использовать другой на константах.
Я работаю с Mac OS X 10.7, Xcode 4.6.2, Clang 3.2, Boost 1.53.0 и расширениями C ++ 11.
Я ценю любую помощь, которая может быть предложена.
Я бы посоветовал вам не использовать арифметику с множественной точностью для моделирования молекулярной динамики, потому что интеграция с шагом по времени будет мучительно медленной. Если цель состоит в том, чтобы максимально сохранить общую энергию, то просто используйте Verlet или любой другой симплектический интегратор. Множественная точность арифметики (или long double
или компенсированное суммирование с простым double
) может быть полезен для агрегирования средних по ансамблю.
Кроме того, если вы напишите свой код моделирования с использованием безразмерных (сокращенных) единиц, вы также избавитесь от зависимости от Boost.Units.
Других решений пока нет …