Skip to content

Commit 1d66d91

Browse files
author
Roberto Di Remigio
committed
Simplify SurfaceFunction class + first working attempt at using Catch for unit tests
1 parent 5cbf1ef commit 1d66d91

File tree

11 files changed

+209
-183
lines changed

11 files changed

+209
-183
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ include(autocmake_int64)
4040
include(autocmake_omp)
4141
include(autocmake_safeguards)
4242
include(autocmake_python_interpreter)
43+
include(pcmsolver)
4344
include(boost_version-components)
4445
include(autocmake_boost)
45-
include(pcmsolver)
4646
include(version)
4747
include(catch)
4848
include(cloc)

cmake/autocmake.cfg

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ source: https://github.com/scisoft/autocmake/raw/master/modules/safeguards.cmake
3838
[python_interpreter]
3939
source: https://github.com/scisoft/autocmake/raw/master/modules/python_interpreter.cmake
4040

41+
[top_level]
42+
source: custom/pcmsolver.cmake
43+
4144
[custom_boost]
4245
source: custom/boost_version-components.cmake
4346

@@ -46,8 +49,7 @@ source: https://github.com/scisoft/autocmake/raw/master/modules/boost/boost.cmak
4649
fetch: http://sourceforge.net/projects/boost/files/boost/1.54.0/boost_1_54_0.zip
4750

4851
[general]
49-
source: custom/pcmsolver.cmake
50-
custom/version.cmake
52+
source: custom/version.cmake
5153
custom/catch.cmake
5254
custom/cloc.cmake
5355
custom/eigen.cmake

cmake/custom/test.cmake

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,5 @@
11
option(ENABLE_TESTS "Enable PCMSolver unit tests" ON)
22

3-
# This macro is used to add a unit test using Boost Unit Testing framework
4-
macro(add_boosttest test_name)
5-
get_filename_component(the_name ${test_name} NAME_WE)
6-
add_executable(${the_name}.x ${the_name}.cpp)
7-
8-
set(_my_libraries "${ARGV1}")
9-
set(_external_libraries "${ARGV2}")
10-
# Find threading library aka CMAKE_THREAD_LIBS_INIT
11-
find_package(Threads)
12-
13-
# Building on more than one processor can result in race conditions,
14-
# since custom Boost can be built only on one processor!
15-
# We thus add this dependency to not get stuck.
16-
if(BUILD_CUSTOM_BOOST)
17-
add_dependencies(${the_name}.x custom_boost)
18-
endif()
19-
target_link_libraries(${the_name}.x
20-
${_my_libraries}
21-
${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
22-
${CMAKE_THREAD_LIBS_INIT}
23-
${_external_libraries}
24-
)
25-
add_test(NAME ${the_name} COMMAND ${the_name}.x)
26-
endmacro()
27-
283
# This macro is used to copy a file containing reference values into the directory
294
# where the unit tests will be executed
305
macro(add_reference reference_file where)

src/interface/Meddle.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ namespace pcm {
219219

220220
// Get the proper iterators
221221
SurfaceFunctionMap::const_iterator iter_pot = functions_.find(MEP);
222-
SurfaceFunction asc(ASC, cavity_->size());
222+
SurfaceFunction asc(cavity_->size());
223223
asc.vector() = K_0_->computeCharge(iter_pot->second.vector(), irrep);
224224
asc /= double(cavity_->pointGroup().nrIrrep());
225225
// Insert it into the map
@@ -237,7 +237,7 @@ namespace pcm {
237237

238238
// Get the proper iterators
239239
SurfaceFunctionMap::const_iterator iter_pot = functions_.find(MEP);
240-
SurfaceFunction asc(ASC, cavity_->size());
240+
SurfaceFunction asc(cavity_->size());
241241
if (hasDynamic_) {
242242
asc.vector() = K_d_->computeCharge(iter_pot->second.vector(), irrep);
243243
} else {
@@ -274,7 +274,7 @@ namespace pcm {
274274
if (functions_.count(functionName) == 1) { // Key in map already
275275
functions_[functionName].vector() = Eigen::Map<Eigen::VectorXd>(values, size, 1);
276276
} else {
277-
SurfaceFunction func(functionName, size, values);
277+
SurfaceFunction func(size, values);
278278
functions_.insert(std::make_pair(functionName, func));
279279
}
280280
}
@@ -286,7 +286,7 @@ namespace pcm {
286286
BOOST_FOREACH(SurfaceFunctionPair pair, functions_) {
287287
unsigned int dim = static_cast<unsigned int>(pair.second.nPoints());
288288
const unsigned int shape[] = {dim};
289-
std::string fname = pair.second.name() + ".npy";
289+
std::string fname = pair.first + ".npy";
290290
cnpy::npy_save(fname, pair.second.vector().data(), shape, 1, "w", true);
291291
}
292292
}
@@ -314,7 +314,7 @@ namespace pcm {
314314
PCMSOLVER_ERROR("Inconsistent dimension of loaded surface function!");
315315
} else {
316316
Eigen::VectorXd values = getFromRawBuffer<double>(dim, 1, raw_surfFunc.data);
317-
SurfaceFunction func(functionName, dim, values);
317+
SurfaceFunction func(dim, values);
318318
// Append to global map
319319
if (functions_.count(functionName) == 1) { // Key in map already
320320
functions_[functionName] = func;

src/utils/SurfaceFunction.cpp

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@
3434
inline void swap(SurfaceFunction & left, SurfaceFunction & right)
3535
{
3636
using std::swap;
37-
swap(left.name_, right.name_);
3837
swap(left.nPoints_,
3938
right.nPoints_); // This is maybe redundant as nPoints must be the same...
4039
swap(left.values_, right.values_);
@@ -43,7 +42,6 @@ inline void swap(SurfaceFunction & left, SurfaceFunction & right)
4342
inline void SurfaceFunction::swap(SurfaceFunction & other)
4443
{
4544
using std::swap;
46-
swap(this->name_, other.name_);
4745
swap(this->nPoints_, other.nPoints_); // This is maybe redundant
4846
swap(this->values_, other.values_);
4947
}
@@ -95,37 +93,13 @@ SurfaceFunction & SurfaceFunction::operator/=(double scaling)
9593
return *this;
9694
}
9795

98-
void SurfaceFunction::setValues(double * v)
99-
{
100-
if (!allocated_)
101-
PCMSOLVER_ERROR("Surface function not allocated!");
102-
// Zero out any previous value
103-
values_.setZero();
104-
105-
for (int i = 0; i < nPoints_; ++i) {
106-
values_(i) = v[i];
107-
}
108-
}
109-
110-
void SurfaceFunction::getValues(double * v)
111-
{
112-
for (int i = 0; i < nPoints_; ++i) {
113-
v[i] = values_(i);
114-
}
115-
}
116-
11796
void SurfaceFunction::clear()
11897
{
11998
values_.setZero();
12099
}
121100

122101
std::ostream & SurfaceFunction::printObject(std::ostream & os)
123102
{
124-
os << "Surface Function " << name_ << std::endl;
125-
if (!allocated_)
126-
PCMSOLVER_ERROR("Surface function not allocated!");
127-
128103
os << values_.transpose();
129-
130104
return os;
131105
}

src/utils/SurfaceFunction.hpp

Lines changed: 9 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -48,32 +48,15 @@
4848
class SurfaceFunction
4949
{
5050
public:
51-
SurfaceFunction() : name_(""), nPoints_(0), allocated_(false) {}
52-
SurfaceFunction(const std::string & n)
53-
: name_(n), nPoints_(0), allocated_(false) {}
54-
SurfaceFunction(const std::string & n, int np)
55-
: name_(n), nPoints_(np) {
56-
values_ = Eigen::VectorXd::Zero(nPoints_);
57-
allocated_ = true;
58-
}
59-
SurfaceFunction(const std::string & n, int np, double * v)
60-
: name_(n), nPoints_(np) {
61-
values_ = Eigen::VectorXd::Zero(nPoints_);
62-
allocated_ = true;
63-
Eigen::Map<Eigen::VectorXd> mapped_data(v, nPoints_);
64-
values_ = mapped_data;
65-
}
66-
SurfaceFunction(const std::string & n, int np, const Eigen::VectorXd & v)
67-
: name_(n), nPoints_(np), values_(v), allocated_(true) {}
68-
~SurfaceFunction() {
69-
allocated_ = false;
70-
}
51+
SurfaceFunction() : nPoints_(0) {}
52+
SurfaceFunction(size_t np) : nPoints_(np), values_(Eigen::VectorXd::Zero(nPoints_)) {}
53+
SurfaceFunction(size_t np, double * v) : nPoints_(np), values_(Eigen::Map<Eigen::VectorXd>(v, nPoints_)) {}
54+
SurfaceFunction(size_t np, const Eigen::VectorXd & v) : nPoints_(np), values_(v) {}
55+
~SurfaceFunction() {}
7156

7257
/// Copy constructor
7358
SurfaceFunction(const SurfaceFunction & other)
74-
: name_(other.name_), nPoints_(other.nPoints_), values_(other.values_) {
75-
allocated_ = true;
76-
}
59+
: nPoints_(other.nPoints_), values_(other.values_) {}
7760

7861
friend inline void swap(SurfaceFunction & left, SurfaceFunction & right);
7962
inline void swap(SurfaceFunction & other);
@@ -90,29 +73,21 @@ class SurfaceFunction
9073
/// Division-assignment operator. Defined only for the uniform scaling case.
9174
SurfaceFunction & operator/=(double scaling);
9275

93-
const std::string & name() const { return name_; }
94-
int nPoints() const { return nPoints_; }
76+
size_t nPoints() const { return nPoints_; }
9577
void value(int index, double value) { values_(index) = value; }
9678
double value(int index) const { return values_(index); }
9779
Eigen::VectorXd & vector() { return values_; }
9880
const Eigen::VectorXd & vector() const { return values_; }
99-
void allocate(int np) { values_.resize(np); }
100-
bool allocated() const { return allocated_; }
10181
void clear();
10282

103-
void setValues(double * v);
104-
void getValues(double * v);
105-
10683
friend std::ostream & operator<<(std::ostream & os, SurfaceFunction & sf) {
10784
return sf.printObject(os);
10885
}
10986

11087
private:
111-
std::ostream & printObject(std::ostream & os);
112-
std::string name_;
113-
int nPoints_;
88+
size_t nPoints_;
11489
Eigen::VectorXd values_;
115-
bool allocated_;
90+
std::ostream & printObject(std::ostream & os);
11691
};
11792

11893
/*!

tests/CMakeLists.txt

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
1-
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
2-
add_executable(catch.x catch.cpp)
3-
unset(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
4-
1+
set_property(GLOBAL PROPERTY TestSources)
52
# Math utilities and helper classes
63
add_subdirectory(surface_function)
7-
add_subdirectory(input)
8-
add_subdirectory(numerical_quadrature)
4+
#add_subdirectory(input)
5+
#add_subdirectory(numerical_quadrature)
96
# Cavity generators
10-
add_subdirectory(gepol)
7+
#add_subdirectory(gepol)
118
# Green's functions
129
#add_subdirectory(dielectric_profile)
13-
add_subdirectory(green)
14-
add_subdirectory(bi_operators)
10+
#add_subdirectory(green)
11+
#add_subdirectory(bi_operators)
1512
# Solvers
16-
add_subdirectory(cpcm)
17-
add_subdirectory(iefpcm)
13+
#add_subdirectory(cpcm)
14+
#add_subdirectory(iefpcm)
15+
16+
get_property(test_sources GLOBAL PROPERTY TestSources)
17+
18+
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
19+
add_executable(unit_tests.x unit_tests.cpp ${test_sources})
20+
target_link_libraries(unit_tests.x pcm)
21+
unset(CMAKE_RUNTIME_OUTPUT_DIRECTORY)
1822

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
set(list_of_libraries utils)
2-
add_boosttest(surface_function "${list_of_libraries}" "${LIBS}")
1+
set_property(GLOBAL APPEND PROPERTY TestSources ${CMAKE_CURRENT_LIST_DIR}/surface_function.cpp)
2+
add_test(NAME surface_function COMMAND unit_tests.x surface_function)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
/* pcmsolver_copyright_start */
2+
/*
3+
* PCMSolver, an API for the Polarizable Continuum Model
4+
* Copyright (C) 2013 Roberto Di Remigio, Luca Frediani and contributors
5+
*
6+
* This file is part of PCMSolver.
7+
*
8+
* PCMSolver is free software: you can redistribute it and/or modify
9+
* it under the terms of the GNU Lesser General Public License as published by
10+
* the Free Software Foundation, either version 3 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* PCMSolver is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* GNU Lesser General Public License for more details.
17+
*
18+
* You should have received a copy of the GNU Lesser General Public License
19+
* along with PCMSolver. If not, see <http://www.gnu.org/licenses/>.
20+
*
21+
* For information on the complete list of contributors to the
22+
* PCMSolver API, see: <http://pcmsolver.github.io/pcmsolver-doc>
23+
*/
24+
/* pcmsolver_copyright_end */
25+
26+
#define BOOST_TEST_MODULE SurfaceFunction
27+
28+
#include <boost/test/unit_test.hpp>
29+
#include <boost/test/floating_point_comparison.hpp>
30+
31+
#include "Config.hpp"
32+
33+
#include <Eigen/Core>
34+
35+
#include "SurfaceFunction.hpp"
36+
37+
struct SurfaceFunctionTest {
38+
int nPoints;
39+
Eigen::VectorXd values1;
40+
Eigen::VectorXd values2;
41+
SurfaceFunction func1;
42+
SurfaceFunction func2;
43+
SurfaceFunctionTest() { SetUp(); }
44+
void SetUp() {
45+
nPoints = 1000;
46+
values1.resize(nPoints);
47+
values2.resize(nPoints);
48+
values1 = Eigen::VectorXd::Random(nPoints);
49+
values2 = Eigen::VectorXd::Random(nPoints);
50+
double * values1_ptr = values1.data();
51+
double * values2_ptr = values2.data();
52+
func1 = SurfaceFunction("TestFunction1", nPoints, values1_ptr);
53+
func2 = SurfaceFunction("TestFunction2", nPoints, values2_ptr);
54+
}
55+
};
56+
57+
/*! \class SurfaceFunction
58+
* \test \b SurfaceFunctionTest_addition tests addition of two SurfaceFunction
59+
*/
60+
BOOST_FIXTURE_TEST_CASE(addition, SurfaceFunctionTest)
61+
{
62+
SurfaceFunction addition = func1 + func2;
63+
BOOST_REQUIRE_EQUAL(nPoints, addition.nPoints());
64+
Eigen::VectorXd result(nPoints);
65+
result = values1 + values2;
66+
for (int i = 0; i < nPoints; ++i) {
67+
BOOST_REQUIRE_CLOSE(result(i), addition.value(i), 1.0e-12);
68+
}
69+
}
70+
71+
/*! \class SurfaceFunction
72+
* \test \b SurfaceFunctionTest_subtraction tests subtraction of two SurfaceFunction
73+
*/
74+
BOOST_FIXTURE_TEST_CASE(subtraction, SurfaceFunctionTest)
75+
{
76+
SurfaceFunction subtraction = func1 - func2;
77+
BOOST_REQUIRE_EQUAL(nPoints, subtraction.nPoints());
78+
Eigen::VectorXd result(nPoints);
79+
result = values1 - values2;
80+
for (int i = 0; i < nPoints; ++i) {
81+
BOOST_REQUIRE_CLOSE(result(i), subtraction.value(i), 1.0e-12);
82+
}
83+
}
84+
85+
/*! \class SurfaceFunction
86+
* \test \b SurfaceFunctionTest_multiply_by_scalar tests multiplication of a SurfaceFunction by a scalar
87+
*/
88+
BOOST_FIXTURE_TEST_CASE(multiply_by_scalar, SurfaceFunctionTest)
89+
{
90+
SurfaceFunction scaled1 = 2.5 * func1;
91+
func2 *= 0.5;
92+
BOOST_REQUIRE_EQUAL(nPoints, scaled1.nPoints());
93+
BOOST_REQUIRE_EQUAL(nPoints, func2.nPoints());
94+
Eigen::VectorXd result1(nPoints), result2(nPoints);
95+
result1 = 2.5 * values1;
96+
result2 = 0.5 * values2;
97+
for (int i = 0; i < nPoints; ++i) {
98+
BOOST_REQUIRE_CLOSE(result1(i), scaled1.value(i), 1.0e-12);
99+
BOOST_REQUIRE_CLOSE(result2(i), func2.value(i), 1.0e-12);
100+
}
101+
}
102+
103+
/*! \class SurfaceFunction
104+
* \test \b SurfaceFunctionTest_multiply tests dot product of two SurfaceFunction
105+
*/
106+
BOOST_FIXTURE_TEST_CASE(multiply, SurfaceFunctionTest)
107+
{
108+
double product = func1 * func2;
109+
double expected_product = values1.dot(values2);
110+
BOOST_REQUIRE_CLOSE(expected_product, product, 1.0e-12);
111+
}

0 commit comments

Comments
 (0)