OGS
LevelSetFunction.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "LevelSetFunction.h"
5
6#include <boost/math/special_functions/sign.hpp>
7#include <numeric>
8#include <range/v3/algorithm/contains.hpp>
9
10#include "BranchProperty.h"
11#include "FractureProperty.h"
12#include "JunctionProperty.h"
13
14namespace
15{
16// Heaviside step function
17inline double Heaviside(bool const v)
18{
19 return v ? 0.5 : -0.5;
20}
21
22} // namespace
23
24namespace ProcessLib
25{
26namespace LIE
27{
28bool levelsetFracture(FractureProperty const& frac, Eigen::Vector3d const& x)
29{
30 return frac.normal_vector.dot(x - frac.point_on_fracture) > 0;
31}
32
33bool levelsetBranch(BranchProperty const& branch, Eigen::Vector3d const& x)
34{
35 return branch.normal_vector_branch.dot(x - branch.coords) > 0;
36}
37
38std::vector<double> uGlobalEnrichments(
39 std::vector<FractureProperty*> const& frac_props,
40 std::vector<JunctionProperty*> const& junction_props,
41 std::unordered_map<int, int> const& fracID_to_local,
42 Eigen::Vector3d const& x)
43{
44 // pre-calculate levelsets for all fractures
45 std::vector<bool> levelsets(frac_props.size());
46 for (std::size_t i = 0; i < frac_props.size(); i++)
47 {
48 levelsets[i] = levelsetFracture(*frac_props[i], x);
49 }
50
51 std::vector<double> enrichments(frac_props.size() + junction_props.size());
52 // fractures possibly with branches
53 for (std::size_t i = 0; i < frac_props.size(); i++)
54 {
55 auto const* frac = frac_props[i];
56 enrichments[i] = Heaviside(
57 std::accumulate(cbegin(frac->branches_slave),
58 cend(frac->branches_slave), levelsets[i],
59 [&](bool const enrich, auto const& branch)
60 { return enrich && levelsetBranch(branch, x); }));
61 }
62
63 // junctions
64 for (std::size_t i = 0; i < junction_props.size(); i++)
65 {
66 auto const* junction = junction_props[i];
67 auto fid1 = fracID_to_local.at(junction->fracture_ids[0]);
68 auto fid2 = fracID_to_local.at(junction->fracture_ids[1]);
69 bool const enrich = levelsets[fid1] && levelsets[fid2];
70 enrichments[i + frac_props.size()] = Heaviside(enrich);
71 }
72
73 return enrichments;
74}
75
76std::vector<double> duGlobalEnrichments(
77 std::size_t this_frac_id,
78 std::vector<FractureProperty*> const& frac_props,
79 std::vector<JunctionProperty*> const& junction_props,
80 std::unordered_map<int, int> const& fracID_to_local,
81 Eigen::Vector3d const& x)
82{
83 auto this_frac_local_index = fracID_to_local.at(this_frac_id);
84 auto const& this_frac = *frac_props[this_frac_local_index];
85 // pre-calculate levelsets for all fractures
86 std::vector<bool> levelsets(frac_props.size());
87 for (std::size_t i = 0; i < frac_props.size(); i++)
88 {
89 levelsets[i] = levelsetFracture(*frac_props[i], x);
90 }
91
92 std::vector<double> enrichments(frac_props.size() + junction_props.size());
93 enrichments[this_frac_local_index] = 1.0;
94
95 // fractures possibly with branches
96 if (frac_props.size() > 1)
97 {
98 for (auto const& branch : this_frac.branches_master)
99 {
100 if (branch.master_fracture_id != this_frac.fracture_id)
101 {
102 continue;
103 }
104
105 if (fracID_to_local.find(branch.slave_fracture_id) ==
106 fracID_to_local.end())
107 {
108 continue;
109 }
110
111 double sign = boost::math::sign(
112 this_frac.normal_vector.dot(branch.normal_vector_branch));
113 auto slave_fid = fracID_to_local.at(branch.slave_fracture_id);
114 double const enrich = levelsets[slave_fid] ? 1. : 0.;
115 enrichments[slave_fid] = sign * enrich;
116 }
117 }
118
119 // junctions
120 for (unsigned i = 0; i < junction_props.size(); i++)
121 {
122 auto const* junction = junction_props[i];
123 if (!ranges::contains(junction->fracture_ids, this_frac.fracture_id))
124 {
125 continue;
126 }
127
128 auto another_frac_id =
129 (junction->fracture_ids[0] == this_frac.fracture_id)
130 ? junction->fracture_ids[1]
131 : junction->fracture_ids[0];
132 auto fid = fracID_to_local.at(another_frac_id);
133 double const enrich = levelsets[fid] ? 1. : 0.;
134 enrichments[i + frac_props.size()] = enrich;
135 }
136
137 return enrichments;
138}
139
140} // namespace LIE
141} // namespace ProcessLib
bool levelsetFracture(FractureProperty const &frac, Eigen::Vector3d const &x)
std::vector< double > duGlobalEnrichments(std::size_t this_frac_id, std::vector< FractureProperty * > const &frac_props, std::vector< JunctionProperty * > const &junction_props, std::unordered_map< int, int > const &fracID_to_local, Eigen::Vector3d const &x)
std::vector< double > uGlobalEnrichments(std::vector< FractureProperty * > const &frac_props, std::vector< JunctionProperty * > const &junction_props, std::unordered_map< int, int > const &fracID_to_local, Eigen::Vector3d const &x)
bool levelsetBranch(BranchProperty const &branch, Eigen::Vector3d const &x)
Eigen::Vector3d const coords