tesseroids/test/test_geometry.c

290 lines
9.1 KiB
C
Raw Normal View History

2021-05-05 10:58:03 +08:00
/*
Unit tests for geometry module.
*/
#include <stdio.h>
#include <math.h>
#include "minunit.h"
#include "../lib/geometry.h"
#include "../lib/constants.h"
/* To store fail messages */
char msg[1000];
static char * test_split_tess()
{
TESSEROID tess = {1, 2, 4, -1, 1, 5, 7},
expect[] = {{1, 2, 3, -1, 0, 5, 6}, {1, 3, 4, -1, 0, 5, 6},
{1, 2, 3, 0, 1, 5, 6}, {1, 3, 4, 0, 1, 5, 6},
{1, 2, 3, -1, 0, 6, 7}, {1, 3, 4, -1, 0, 6, 7},
{1, 2, 3, 0, 1, 6, 7}, {1, 3, 4, 0, 1, 6, 7}},
res[8];
int i, n;
n = split_tess(tess, 2, 2, 2, res);
sprintf(msg, "splitting in %d instead of 8", n);
mu_assert(n == 8, msg);
for(i = 0; i < 8; i++)
{
sprintf(msg, "failed for split %d: %g %g %g %g %g %g %g", i, res[i].w,
res[i].e, res[i].s, res[i].n, res[i].r1, res[i].r2,
res[i].density);
mu_assert(res[i].w == expect[i].w && res[i].e == expect[i].e &&
res[i].s == expect[i].s && res[i].n == expect[i].n &&
res[i].r1 == expect[i].r1 && res[i].r2 == expect[i].r2 &&
res[i].density == expect[i].density, msg);
}
return 0;
}
static char * test_split_uneven_tess()
{
TESSEROID tess = {1, 2, 4, -1, 1, 5, 7},
expect[] = {{1, 2, 3, -1, 0, 5, 7}, {1, 3, 4, -1, 0, 5, 7},
{1, 2, 3, 0, 1, 5, 7}, {1, 3, 4, 0, 1, 5, 7}},
res[4];
int i, n;
n = split_tess(tess, 2, 2, 1, res);
sprintf(msg, "splitting in %d instead of 4", n);
mu_assert(n == 4, msg);
for(i = 0; i < 4; i++)
{
sprintf(msg, "failed for split %d: %g %g %g %g %g %g %g", i, res[i].w,
res[i].e, res[i].s, res[i].n, res[i].r1, res[i].r2,
res[i].density);
mu_assert(res[i].w == expect[i].w && res[i].e == expect[i].e &&
res[i].s == expect[i].s && res[i].n == expect[i].n &&
res[i].r1 == expect[i].r1 && res[i].r2 == expect[i].r2 &&
res[i].density == expect[i].density, msg);
}
return 0;
}
static char * test_prism_volume()
{
PRISM prisms[4] = {
{0,0,1,0,1,0,1,0,0,0},
{0,0,2,0,1,0,1,0,0,0},
{0,0,2,0,2,0,2,0,0,0},
{0,1,2,-1,1,2,3,0,0,0}};
double pvolumes[4] = {1, 2, 8, 2};
double res;
int i;
for(i = 0; i < 4; i++)
{
res = prism_volume(prisms[i]);
sprintf(msg, "(prism %d) expected %g, got %g", i, pvolumes[i], res);
mu_assert(res == pvolumes[i], msg);
}
return 0;
}
static char * test_tess_volume()
{
TESSEROID tesses[4] = {{0,0,360,-90,90,0,1}, {0,0,360,0,90,0,1},
{0,180,360,0,90,0,1}, {0,0,90,-90,0,0,1}};
double tvolumes[4] = {4.188790205, 2.094395102, 1.047197551, 0.523598776};
double res;
int i;
for(i = 0; i < 4; i++)
{
res = tess_volume(tesses[i]);
sprintf(msg, "(tess %d) expected %g, got %g", i, tvolumes[i], res);
mu_assert_almost_equals(res, tvolumes[i], pow(10, -8), msg);
}
return 0;
}
static char * test_tess_total_mass()
{
TESSEROID tesses[4] = {{1,0,360,-90,90,0,1}, {1,0,360,0,90,0,1},
{1,180,360,0,90,0,1}, {1,0,90,-90,0,0,1}};
double tvolumes[4] = {4.188790205, 2.094395102, 1.047197551, 0.523598776};
double res, expect;
int i;
res = tess_total_mass(tesses, 4);
for(expect = 0, i = 0; i < 4; i++)
{
expect += tvolumes[i];
}
sprintf(msg, "(tess %d) expected %g, got %g", i, expect, res);
mu_assert_almost_equals(res, expect, pow(10, -6), msg);
return 0;
}
static char * test_tess_range_mass()
{
TESSEROID tesses[4] = {{1,0,360,-90,90,0,1}, {-1,0,360,0,90,0,1},
{-1,180,360,0,90,0,1}, {1,0,90,-90,0,0,1}};
double tvolumes[4] = {4.188790205, 2.094395102, 1.047197551, 0.523598776};
double res, expect;
res = tess_range_mass(tesses, 4, 0, 1);
expect = tvolumes[0] + tvolumes[3];
sprintf(msg, "Expected %g, got %g", expect, res);
mu_assert_almost_equals(res, expect, pow(10, -6), msg);
return 0;
}
static char * test_tess2prism()
{
int i;
double expect, res;
double lons[4] = {0.5, 185, 180, -2.5},
lats[4] = {0.5, 82.5, -80, 4},
rs[4] = {6001000, 6301000, 6000000, 6505000},
zs[4] = {1000, 1000, 500000, 5000};
PRISM prism;
TESSEROID tesses[4] = {
{1,0,1,0,1,6000000,6001000},
{1,180,190,80,85,6300000,6301000},
{1,160,200,-90,-70,5500000,6000000},
{1,-10,5,-7,15,6500000,6505000}};
for(i = 0; i < 4; i++)
{
tess2prism(tesses[i], &prism);
/* check the volume */
res = prism_volume(prism);
expect = tess_volume(tesses[i]);
sprintf(msg, "(tess %d) expected volume %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.01, msg);
/* check the mass */
res *= prism.density;
expect *= tesses[i].density;
sprintf(msg, "(tess %d) expected mass %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.01, msg);
/* check the coordinates */
res = prism.lon;
expect = lons[i];
sprintf(msg, "(tess %d) expected lon %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.0001, msg);
res = prism.lat;
expect = lats[i];
sprintf(msg, "(tess %d) expected lat %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.0001, msg);
res = prism.r;
expect = rs[i];
sprintf(msg, "(tess %d) expected r %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.0001, msg);
res = prism.z1;
expect = 0.;
sprintf(msg, "(tess %d) expected z1 %g, got %g", i, expect, res);
mu_assert_almost_equals(res, 0., 0.000000000000001, msg);
res = prism.z2;
expect = zs[i];
sprintf(msg, "(tess %d) expected z2 %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.0001, msg);
}
return 0;
}
static char * test_tess2prism_flatten()
{
double expect, res;
PRISM prism;
int i;
TESSEROID tesses[4] = {
{1,0,1,0,1,6000000,6001000},
{1,180,190,80,85,6300000,6301000},
{1,160,200,-90,-70,5500000,6000000},
{1,-10,5,-7,15,6500000,6505000}};
for(i = 0; i < 4; i++)
{
tess2prism_flatten(tesses[i], &prism);
res = prism_volume(prism)*prism.density;
expect = tess_volume(tesses[i])*tesses[i].density;
sprintf(msg, "(tess %d) expected mass %g, got %g", i, expect, res);
mu_assert_almost_equals((double)(res - expect)/expect, 0., 0.01, msg);
}
return 0;
}
static char * test_tess2sphere()
{
double expect, res;
SPHERE sphere;
int i;
TESSEROID tesses[4] = {
{1,0,1,0,1,6000000,6001000},
{1,180,190,80,85,6300000,6301000},
{1,160,200,-90,-70,5500000,6000000},
{1,-10,5,-7,15,6500000,6505000}};
for(i = 0; i < 4; i++)
{
tess2sphere(tesses[i], &sphere);
res = sphere_volume(sphere);
expect = tess_volume(tesses[i]);
sprintf(msg, "(tess %d) expected volume %g, got %g", i, expect, res);
mu_assert_almost_equals(res/expect, 1., 0.01, msg);
}
return 0;
}
static char * test_prism2sphere()
{
double expect, res;
SPHERE sphere;
int i;
PRISM prisms[4] = {
{1,0,1000,0,2000,100,2000,0,0,0},
{1,-500,200,300,500,-1000,4000,0,0,0},
{1,-10000000,5000000,5000000,8000000,0,3000000,0,0,0},
{1,-1000000,50000,500000,800000,0,300000,0,0,0}};
for(i = 0; i < 4; i++)
{
prism2sphere(prisms[i], 0., 0., 0., &sphere);
res = sphere_volume(sphere);
expect = prism_volume(prisms[i]);
sprintf(msg, "(prism %d) expected volume %g, got %g", i, expect, res);
mu_assert_almost_equals(res/expect, 1., 0.001, msg);
}
return 0;
}
int geometry_run_all()
{
int failed = 0;
failed += mu_run_test(test_prism_volume, "prism_volume return correct results");
failed += mu_run_test(test_tess_volume, "tess_volume return correct results");
failed += mu_run_test(test_tess_total_mass, "tess_total_mass returns correct result");
failed += mu_run_test(test_tess_range_mass, "tess_range_mass returns correct result");
failed += mu_run_test(test_tess2prism, "tess2prism produces prism with right volume");
failed += mu_run_test(test_tess2prism_flatten,
"tess2prism_flatten produces prism with right mass");
failed += mu_run_test(test_tess2sphere,
"tess2sphere produces sphere with right volume");
failed += mu_run_test(test_prism2sphere,
"prism2sphere produces sphere with right volume");
failed += mu_run_test(test_split_tess, "split_tess returns correct results for 2, 2, 2 split");
failed += mu_run_test(test_split_uneven_tess, "split_tess returns correct results for 2, 2, 1 split");
return failed;
}