Plugins
Loading...
Searching...
No Matches
richards_fs_height_impl.h
Go to the documentation of this file.
1//
2// Created by julian on 2/27/26.
3//
4
5#ifndef UG4_RICHARDS_FS_HEIGHT_IMPL_H
6#define UG4_RICHARDS_FS_HEIGHT_IMPL_H
8#ifdef UG_PARALLEL
11#endif
12namespace ug {
13namespace d3f {
14
15// -------------------------------------------------------------------------
16// Constructor Implementation
17// -------------------------------------------------------------------------
18template<typename TGridFunction>
20(
22 const char *subset,
23 const char *cmp
24)
25 :m_spGf(spGf),
26 m_cmp(cmp),
27 m_glob_userdata(spGf, cmp),
28 m_sp_ls_pos_z(spGf, spGf->fct_id_by_name(cmp), 0) // Sets up the level set position measurer for z-direction
29{
31 // Set up the subset group to restrict operations to the specified boundary (e.g., "top")
32 m_SsGrp.set_subset_handler(spGf->domain()->subset_handler());
34 m_sp_vrt_val = make_sp(new std::vector<number>());
35 // Attach a vertex numbering property to the grid to uniquely identify vertices during evaluation
36 spGf->domain()->grid()->attach_to_vertices_dv(m_a_vrt_num, -1);
37 spGf->domain()->grid()->attach_to_vertices_dv(m_a_vrt_val, 0.0);
38
39}
40
41// -------------------------------------------------------------------------
42// Reinit Implementation
43// -------------------------------------------------------------------------
44 template<typename TGridFunction>
46
47 m_sp_ls_pos_z.reinit();
48
49 Grid& grid = *m_spGf->domain()->grid();
50
51 // Attachment access for global index and vertex position
52 num_aa_type aa_vrt_num (grid, m_a_vrt_num);
53 val_aa_type aa_vrt_val (grid, m_a_vrt_val);
54 auto vAccPos = m_spGf->domain()->position_accessor();
55
56 // Clear previous cached measurements
57 m_measurement_points.clear();
58 m_sp_vrt_val->clear();
59
60 size_t n = 0; // Global index counter for the vertices in the subset
61
62 // Vector to collect local vertices to update cached vectors after communication
63 std::vector<Vertex*> local_vertices;
64
65 // --- Phase 1: Local Setup & Evaluation ---
66 for (size_t i = 0; i < m_SsGrp.size (); i++)
67 {
68 int si = m_SsGrp[i];
69
70 for (auto iter = m_spGf->template begin<Vertex> (si);
71 iter != m_spGf->template end<Vertex> (si); ++iter, ++n) {
72
73 aa_vrt_num[*iter] = n;
74 local_vertices.push_back(*iter);
75
76 // Extract the lower-dimensional (x, y) coordinates
77 MathVector<dim - 1> xy_coords;
78 for (size_t d = 0; d < dim - 1; d++) {
79 xy_coords[d] = vAccPos[*iter][d];
80 }
81
82 // Create a new measurement point and add it to our tracking vector
83 m_measurement_points.push_back(xy_coords);
84 m_sp_vrt_val->push_back(0); // pre-allocate
85
86 auto& pnt = m_measurement_points.back();
87 pnt.valid = m_sp_ls_pos_z.get_height_at(pnt.xy, pnt.z);
88
89 if (pnt.valid) {
90 aa_vrt_val[*iter] = pnt.z;
91 } else {
92 // If invalid locally, assign a highly negative sentinel for the MAX reduction
93 aa_vrt_val[*iter] = -std::numeric_limits<number>::max();
94 }
95 }
96 }
97
98#ifdef UG_PARALLEL
99 // --- Phase 2: Interface Direct Communication ---
100 // Extract layout types and manager strictly for Vertices
101 typedef typename GridLayoutMap::Types<Vertex>::Layout layout_t;
102 DistributedGridManager& dgm = *grid.distributed_grid_manager();
103 GridLayoutMap& glm = dgm.grid_layout_map();
105
106 // We extract the exact Attachment type defined
107 typedef decltype(m_a_vrt_val) a_val_type;
108
109 // 1. REDUCE: Send local values from Slaves to Master and take the MAX
110 // We use MAX so the valid height beats the -MAX sentinel
112 icom.exchange_data(glm, INT_H_SLAVE, INT_H_MASTER, compolMax);
113 icom.communicate();
114
115 // 2. COPY: Broadcast the winning MAX value from Master back to all Slave nodes
116 ComPol_CopyAttachment<layout_t, a_val_type> compolCopy(grid, m_a_vrt_val);
117 icom.exchange_data(glm, INT_H_MASTER, INT_H_SLAVE, compolCopy);
118 icom.communicate();
119
120
121#endif
122
123 // --- Phase 3: Finalize Caches ---
124 // Now that the attachment has been synced natively, we read it back
125 // to populate your structs and m_sp_vrt_val for eval_and_deriv
126 for (size_t j = 0; j < local_vertices.size(); j++) {
127 Vertex* vrt = local_vertices[j];
128 number synced_z = aa_vrt_val[vrt];
129 auto& pnt = m_measurement_points[j];
130
131 if (synced_z == -std::numeric_limits<number>::max()) {
132 // No process found the surface at this node
133 pnt.valid = false;
134 pnt.z = 0.0;
135 aa_vrt_val[vrt] = 0.0; // Clean up the sentinel
136 } else {
137 // Surface was found!
138 pnt.valid = true;
139 pnt.z = synced_z;
140 (*m_sp_vrt_val)[j] = synced_z;
141 }
142 }
143}
144
145
146// -------------------------------------------------------------------------
147// Evaluation Implementation
148// -------------------------------------------------------------------------
149template<typename TGridFunction>
150template<int refDim>
152(
153 number vValue[],
154 const MathVector<dim> vGlobIP[],
155 number time,
156 int si,
157 GridObject* grid_obj,
158 const MathVector<dim> vCornerCoords[],
159 const MathVector<refDim> vLocIP[],
160 const size_t nip,
161 LocalVector* u,
162 bool bDeriv,
163 int s,
164 std::vector<std::vector<number> > vvvDeriv[],
165 const MathMatrix<refDim, dim>* vJT
166)
167{
168 typedef typename gf_type::template dim_traits<refDim>::grid_base_object elem_type;
169
170 // Guard against evaluating on a subset we didn't cache data for
171 if (! m_SsGrp.contains (si))
172 UG_THROW ("RichardsFreeSurfaceHeight: Attempt to get the value for a subset that has not been specified.");
173
174 // Cast to the correct element type and fetch local shape functions for interpolation
175 const ReferenceObjectID roid = grid_obj->reference_object_id ();
176 const elem_type * elem = dynamic_cast<elem_type *> (grid_obj);
177 const LocalShapeFunctionSet<refDim> & rTrialSpace =
178 LocalFiniteElementProvider::get<refDim> (roid, LFEID (LFEID::LAGRANGE, refDim, 1));
179
180 num_aa_type aa_vrt_num (* m_spGf->domain()->grid (), m_a_vrt_num);
181 val_aa_type aa_vrt_val (* m_spGf->domain()->grid (), m_a_vrt_val);
182 std::vector<number> shape;
183
184 // Loop over all integration points (IPs) within the element
185 for (size_t ip = 0; ip < nip; ++ip) {
186 // Evaluate the shape functions at the local coordinate of the current IP
187 rTrialSpace.shapes (shape, vLocIP [ip]);
188
189 // Initialize the interpolated value
190 vValue [ip] = 0;
191
192 // Interpolate the height using the vertex values and shape functions
193 for (size_t sh = 0; sh < shape.size (); ++sh) {
194 const Vertex* vrt = elem->vertex (sh);
195 size_t vrt_no = aa_vrt_num [vrt]; // Retrieve our cached vertex index
196
197 // Check if a valid free surface was found at this vertex during reinit()
198 if (m_measurement_points[vrt_no].valid) {
199 // Surface found: use the cached free surface height (z)
200 //UG_LOG("valid vertex"<<vrt_no<<": " << aa_vrt_val[vrt]<< "\n")
201 vValue [ip] += aa_vrt_val[vrt] * shape [sh];
202 }
203 else {
204 // Surface NOT found (e.g., domain is fully saturated and free surface is above it)
205 // Fallback: use the physical z-coordinate of the domain boundary vertex
206 //UG_LOG("invalid vertex"<<vrt_no<<": " << vCornerCoords[sh][dim -1]<< "\n")
207 vValue [ip] += vCornerCoords[sh][dim -1] * shape [sh];
208 }
209 }
210 }
211}
212}
213}
214
215
216#endif //UG4_RICHARDS_FS_HEIGHT_IMPL_H
parameterString s
Definition Biogas.lua:2
bool communicate(int tag=749345)
void exchange_data(const TLayoutMap &layoutMap, const typename TLayoutMap::Key &keyFrom, const typename TLayoutMap::Key &keyTo, ICommunicationPolicy< TLayout > &commPol)
GridLayoutMap & grid_layout_map()
virtual ReferenceObjectID reference_object_id() const=0
int subset() const
virtual void shapes(std::vector< std::vector< shape_type > > &vvShape, const std::vector< MathVector< dim > > &vLocPos) const=0
void add(const char *name)
void set_subset_handler(ConstSmartPtr< ISubsetHandler > sh)
void reinit()
initialize the object: find the intersected elements and prepare the tree
Definition level_set_pos.h:139
SubsetGroup m_SsGrp
Definition richards_fs_height.h:109
val_a_type m_a_vrt_val
Definition richards_fs_height.h:114
void reinit()
Reinitializes the measurer.
Definition richards_fs_height_impl.h:45
RichardsFreeSurfaceHeight(SmartPtr< gf_type > spGf, const char *subset="top", const char *cmp="p")
Constructor for RichardsFreeSurfaceHeight.
Definition richards_fs_height_impl.h:20
num_a_type m_a_vrt_num
Definition richards_fs_height.h:113
void eval_and_deriv(number vValue[], const MathVector< dim > vGlobIP[], number time, int si, GridObject *elem, const MathVector< dim > vCornerCoords[], const MathVector< refDim > vLocIP[], const size_t nip, LocalVector *u, bool bDeriv, int s, std::vector< std::vector< number > > vvvDeriv[], const MathMatrix< refDim, dim > *vJT=NULL)
Evaluates the free surface height at integration points of a grid element.
Definition richards_fs_height_impl.h:152
measurer_type m_sp_ls_pos_z
Definition richards_fs_height.h:116
SmartPtr< std::vector< number > > m_sp_vrt_val
Definition richards_fs_height.h:115
SmartPtr< TGrid > grid()
vector< string > TokenizeString(const char *str, const char delimiter=',')
#define UG_THROW(msg)
double number
ReferenceObjectID
INT_H_MASTER
INT_H_SLAVE
SmartPtr< T, FreePolicy > make_sp(T *inst)