Skip to content

Commit 4adda92

Browse files
authored
Merge pull request #27 from Geode-solutions/spatial_window
Spatial_window
2 parents a14d16e + 0869b0f commit 4adda92

25 files changed

Lines changed: 845 additions & 283 deletions

bindings/python/src/stochastic/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ add_geode_python_binding(
2828
"sampling/direct/double_sampler.hpp"
2929
"sampling/random_engine.hpp"
3030
"sampling/distributions.hpp"
31+
"spatial/spatial_domain.hpp"
3132
"stochastic.cpp"
3233
DEPENDENCIES
3334
${PROJECT_NAME}::stochastic

bindings/python/src/stochastic/sampling/mcmc/helpers/fracture_simulation_runner.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ namespace geode
5353
pybind11::class_< FractureSimulationRunner,
5454
std::shared_ptr< FractureSimulationRunner > >(
5555
module, "FractureSimulationRunner" )
56-
.def( pybind11::init< const BoundingBox2D& >(),
56+
.def( pybind11::init< const SpatialDomain< 2 >& >(),
5757
pybind11::arg( "box" ) )
5858
.def( "add_fracture_set_descriptor",
5959
&FractureSimulationRunner::add_fracture_set_descriptor,
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/*
2+
* Copyright (c) 2019 - 2025 Geode-solutions
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*
22+
*/
23+
24+
#include <geode/stochastic/spatial/spatial_domain.hpp>
25+
26+
namespace
27+
{
28+
template < geode::index_t dimension >
29+
void declare_spatial_domain( pybind11::module& module )
30+
{
31+
using Domain = geode::SpatialDomain< dimension >;
32+
using BBox = geode::BoundingBox< dimension >;
33+
34+
const auto pyclass_name =
35+
"SpatialDomain" + std::to_string( dimension ) + "D";
36+
37+
pybind11::class_< Domain >( module, pyclass_name.c_str() )
38+
.def( pybind11::init< const BBox&, double >(),
39+
pybind11::arg( "domain" ), pybind11::arg( "buffer_size" ),
40+
R"doc(
41+
Create a spatial domain composed of:
42+
43+
- a core domain (the VOI)
44+
- a buffer zone
45+
- the extended domain (domain + buffer)
46+
47+
Arguments:
48+
domain (BoundingBox): main domain / VOI
49+
buffer_size (float): buffer thickness
50+
)doc" );
51+
}
52+
} // namespace
53+
namespace geode
54+
{
55+
void define_spatial_domain( pybind11::module& module )
56+
{
57+
declare_spatial_domain< 2 >( module );
58+
declare_spatial_domain< 3 >( module );
59+
}
60+
} // namespace geode

bindings/python/src/stochastic/stochastic.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,16 @@
3333

3434
#include "sampling/distributions.hpp"
3535
#include "sampling/random_engine.hpp"
36+
#include "spatial/spatial_domain.hpp"
3637

3738
PYBIND11_MODULE( opengeode_stochastic_py_stochastic, module )
3839
{
3940
module.doc() = "OpenGeode-Stochastic Python binding";
4041
pybind11::class_< geode::StochasticLibrary >( module, "StochasticLibrary" )
4142
.def( "initialize", &geode::StochasticLibrary::initialize );
4243

44+
geode::define_spatial_domain( module );
45+
4346
geode::define_distributions( module );
4447
geode::define_random_engine( module );
4548
geode::define_double_sampler( module );

bindings/python/tests/stochastic/test-py-mh-fractures.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ def test_fracture_simulator():
4141
box = og.BoundingBox2D()
4242
box.add_point(og.Point2D([0.0, 0.0]))
4343
box.add_point(og.Point2D([100.0, 100.0]))
44+
domain = stochastic.SpatialDomain2D(box,10.)
4445

4546
# --- Object set
4647
setA = stochastic.FractureSetDescription()
@@ -60,7 +61,7 @@ def test_fracture_simulator():
6061
setA.p20 = 0.06
6162
setA.minimal_spacing = 1.0
6263

63-
runner = stochastic.FractureSimulationRunner(box)
64+
runner = stochastic.FractureSimulationRunner(domain)
6465
runner.add_fracture_set_descriptor(setA)
6566
runner.initialize()
6667

@@ -90,7 +91,7 @@ def test_two_fracture_sets_simulator():
9091
box = og.BoundingBox2D()
9192
box.add_point(og.Point2D([0.0, 0.0]))
9293
box.add_point(og.Point2D([100.0, 100.0]))
93-
94+
domain = stochastic.SpatialDomain2D(box,10.)
9495
# --- Object set A
9596
setA = stochastic.FractureSetDescription()
9697
setA.name = "A"
@@ -117,7 +118,7 @@ def test_two_fracture_sets_simulator():
117118
setB.p20 = 0.03
118119
setB.minimal_spacing = 2.0
119120

120-
runner = stochastic.FractureSimulationRunner(box)
121+
runner = stochastic.FractureSimulationRunner(domain)
121122
runner.add_fracture_set_descriptor(setA)
122123
runner.add_fracture_set_descriptor(setB)
123124
runner.initialize()

include/geode/stochastic/sampling/direct/object_set_sampler/point_set_sampler.hpp

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,60 +28,72 @@
2828

2929
#include <geode/stochastic/sampling/direct/object_set_sampler/object_set_sampler.hpp>
3030
#include <geode/stochastic/sampling/direct/point_uniform_sampler.hpp>
31+
#include <geode/stochastic/spatial/spatial_domain.hpp>
3132

3233
namespace geode
3334
{
3435
template < index_t dimension >
3536
class UniformPointSetSampler : public ObjectSetSampler< Point< dimension > >
3637
{
3738
public:
38-
UniformPointSetSampler( const BoundingBox< dimension >& box )
39-
: ObjectSetSampler< Point< dimension > >{}, box_( box )
39+
UniformPointSetSampler( const SpatialDomain< dimension >& domain )
40+
: ObjectSetSampler< Point< dimension > >{}, domain_( domain )
4041
{
41-
auto volume = box_.n_volume();
42+
auto volume = domain_.extended_n_volume();
4243
OPENGEODE_EXCEPTION( volume != 0.,
43-
"[PointSetSampler] - Undefined Bounding Box (volume ==0)." );
44+
"[PointSetSampler] - Undefined Extended Bounding "
45+
"Box (volume ==0)." );
4446
this->log_pdf_ = -std::log( volume );
47+
step_move_ = define_step_for_move();
48+
OPENGEODE_EXCEPTION( step_move_ > 0.,
49+
"[PointSetSampler] - Undefined step length for move (value == ",
50+
step_move_, ")." );
4551
}
4652

4753
Point< dimension > sample( RandomEngine& engine ) const override
4854
{
49-
return PointUniformSampler::sample< dimension >( engine, box_ );
55+
return PointUniformSampler::sample< dimension >(
56+
engine, domain_.extended_box() );
5057
}
5158

5259
Point< dimension > change(
5360
const Point< dimension >& obj, RandomEngine& engine ) const override
5461
{
55-
double ratio = 0.1;
56-
geode::Sphere< dimension > ball{ obj,
57-
ratio * std::get< 1 >( box_.smallest_length() ) };
62+
geode::Sphere< dimension > ball{ obj, step_move_ };
5863

5964
auto new_point =
6065
PointUniformSampler::sample< dimension >( engine, ball );
6166
constexpr index_t max_try{ 100 };
6267
for( const auto try_id : geode::Range{ max_try } )
6368
{
64-
if( box_.contains( new_point ) )
69+
if( domain_.extended_contains( new_point ) )
6570
{
6671
return new_point;
6772
}
6873
new_point =
6974
PointUniformSampler::sample< dimension >( engine, ball );
7075
}
71-
throw OpenGeodeException( absl::StrCat(
72-
"[PointSampler] - Cannot find a point in the box: ",
73-
box_.string() ) );
76+
throw OpenGeodeException(
77+
absl::StrCat( "[PointSampler] - Cannot find a point in the "
78+
"extended domain" ) );
7479
return obj;
7580
}
7681

7782
private:
83+
double define_step_for_move()
84+
{
85+
double ratio = 0.1;
86+
return ratio * domain_.smallest_length();
87+
}
88+
7889
bool is_valid_object( const Point< dimension >& obj ) const override
7990
{
80-
return box_.contains( obj );
91+
return domain_.extended_contains( obj );
8192
}
8293

8394
private:
84-
BoundingBox< dimension > box_;
95+
const SpatialDomain< dimension >& domain_;
96+
double step_move_{ 0. };
8597
};
8698

8799
} // namespace geode

include/geode/stochastic/sampling/direct/object_set_sampler/segment_set_sampler.hpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,30 +29,32 @@
2929
#include <geode/stochastic/sampling/direct/object_set_sampler/object_set_sampler.hpp>
3030
#include <geode/stochastic/sampling/direct/point_uniform_sampler.hpp>
3131
#include <geode/stochastic/sampling/direct/segment_uniform_sampler.hpp>
32+
#include <geode/stochastic/spatial/spatial_domain.hpp>
3233

3334
namespace geode
3435
{
3536
class UniformSegmentSetSampler : public ObjectSetSampler< OwnerSegment2D >
3637
{
3738
public:
38-
UniformSegmentSetSampler( const BoundingBox< 2 >& box,
39+
UniformSegmentSetSampler( const SpatialDomain< 2 >& domain,
3940
const DoubleSampler::Distribution& length,
4041
const DoubleSampler::Distribution& azimuth )
4142
: ObjectSetSampler< OwnerSegment2D >{},
42-
box_{ box },
43+
domain_{ domain },
4344
length_{ length },
4445
azimuth_{ azimuth }
4546
{
46-
auto volume = box_.n_volume();
47+
auto volume = domain_.extended_n_volume();
4748
OPENGEODE_EXCEPTION( volume != 0.,
48-
"[SegmentSetSampler] - Undefined Bounding Box (volume == 0)." );
49+
"[SegmentSetSampler] - Undefined Extended Bounding "
50+
"Box (volume ==0)." );
4951
this->log_pdf_ = -std::log( volume );
5052
}
5153

5254
OwnerSegment2D sample( RandomEngine& engine ) const override
5355
{
5456
auto seg = SegmentUniformSampler::sample(
55-
engine, box_, length_, azimuth_ );
57+
engine, domain_.extended_box(), length_, azimuth_ );
5658
return seg;
5759
}
5860

@@ -72,8 +74,8 @@ namespace geode
7274
constexpr index_t max_try{ 100 };
7375
for( const auto try_id : geode::Range{ max_try } )
7476
{
75-
if( box_.contains( new_point )
76-
|| box_.contains( extremities[other] ) )
77+
if( domain_.extended_contains( new_point )
78+
|| domain_.extended_contains( extremities[other] ) )
7779
{
7880
OwnerSegment2D new_segment{ obj };
7981
new_segment.set_point( current, new_point );
@@ -82,22 +84,20 @@ namespace geode
8284
new_point = PointUniformSampler::sample< 2 >( engine, ball );
8385
}
8486
throw OpenGeodeException( absl::StrCat(
85-
"[PointSampler] - Cannot find a point in the box: ",
86-
box_.string() ) );
87+
"[SegmentSetSampler] - Cannot find a point in the box" ) );
8788
return obj;
8889
}
8990

9091
private:
9192
bool is_valid_object( const OwnerSegment2D& obj ) const override
9293
{
9394
const auto& extremities = obj.vertices();
94-
95-
return box_.contains( extremities[0] )
96-
|| box_.contains( extremities[1] );
95+
return domain_.extended_contains( extremities[0] )
96+
|| domain_.extended_contains( extremities[1] );
9797
}
9898

9999
private:
100-
BoundingBox2D box_;
100+
const SpatialDomain< 2 >& domain_;
101101
DoubleSampler::Distribution length_;
102102
DoubleSampler::Distribution azimuth_;
103103
};

include/geode/stochastic/sampling/mcmc/helpers/fracture_simulation_runner.hpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include <geode/stochastic/sampling/mcmc/models/components/pairwise_term.hpp>
3333
#include <geode/stochastic/sampling/mcmc/proposal/classical_proposals.hpp>
3434
#include <geode/stochastic/spatial/pairwise_interactions.hpp>
35+
#include <geode/stochastic/spatial/spatial_domain.hpp>
3536

3637
namespace geode
3738
{
@@ -72,7 +73,10 @@ namespace geode
7273
class FractureSimulationRunner : public SimulationRunner< OwnerSegment2D >
7374
{
7475
public:
75-
FractureSimulationRunner( const BoundingBox2D& box ) : box_( box ) {}
76+
FractureSimulationRunner( const SpatialDomain< 2 >& domain )
77+
: SimulationRunner< OwnerSegment2D >( domain )
78+
{
79+
}
7680

7781
void add_fracture_set_descriptor(
7882
const FractureSetDescription& descriptor )
@@ -101,7 +105,7 @@ namespace geode
101105
set_desc.azimuth );
102106
this->set_samplers_.push_back(
103107
std::make_unique< UniformSegmentSetSampler >(
104-
box_, length_distribution, azimuth_distribution ) );
108+
domain_, length_distribution, azimuth_distribution ) );
105109

106110
add_birth_death_change_moves( this->set_samplers_.back(),
107111
*proposal_kernel, set_id, set_desc.birth_ratio,
@@ -117,7 +121,8 @@ namespace geode
117121
this->energy_terms_collection_.add_energy_term(
118122
std::make_unique< DensityTerm< OwnerSegment2D > >(
119123
absl::StrCat( set_desc.name, "_density" ),
120-
set_desc.p20, std::vector< uuid >{ set_id } ) ) );
124+
set_desc.p20, std::vector< uuid >{ set_id },
125+
this->domain_ ) ) );
121126
// spacing
122127
if( set_desc.minimal_spacing < GLOBAL_EPSILON )
123128
{
@@ -133,7 +138,7 @@ namespace geode
133138
std::make_unique< PairwiseTerm< OwnerSegment2D > >(
134139
absl::StrCat( set_desc.name, "_min_spacing" ), 0.,
135140
std::vector< uuid >{ set_id },
136-
std::move( interaction ) ) ) );
141+
std::move( interaction ), this->domain_ ) ) );
137142
}
138143

139144
this->mh_sampler_ =
@@ -159,7 +164,6 @@ namespace geode
159164
}
160165

161166
private:
162-
BoundingBox2D box_;
163167
std::vector< FractureSetDescription > set_descriptors_;
164168
};
165169

include/geode/stochastic/sampling/mcmc/helpers/simulation_runner.hpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <geode/stochastic/sampling/mcmc/helpers/simulation_printer.hpp>
2828
#include <geode/stochastic/sampling/mcmc/metropolis_hasting_sampler.hpp>
2929
#include <geode/stochastic/sampling/mcmc/models/energy_term_collection.hpp>
30+
#include <geode/stochastic/spatial/spatial_domain.hpp>
3031

3132
#include <absl/strings/str_join.h>
3233

@@ -62,7 +63,8 @@ namespace geode
6263
class SimulationRunner
6364
{
6465
public:
65-
SimulationRunner() = default;
66+
SimulationRunner( const SpatialDomain< ObjectType::dim >& domain )
67+
: domain_( domain ) {};
6668
virtual ~SimulationRunner() = default;
6769

6870
virtual void initialize() = 0;
@@ -153,6 +155,7 @@ namespace geode
153155
}
154156

155157
protected:
158+
SpatialDomain< ObjectType::dim > domain_;
156159
std::vector< std::unique_ptr< geode::ObjectSetSampler< ObjectType > > >
157160
set_samplers_;
158161

0 commit comments

Comments
 (0)