SheafSystem  0.0.0.0
section_iteration_state.cc
1 
2 //
3 // Copyright (c) 2014 Limit Point Systems, Inc.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 
18 // Implementation for class section_iteration_state
19 
20 #include "SheafSystem/section_iteration_state.h"
21 
22 #include "SheafSystem/assert_contract.h"
23 #include "SheafSystem/base_space_poset.h"
24 #include "SheafSystem/binary_section_space_schema_member.h"
25 #include "SheafSystem/block.impl.h"
26 #include "SheafSystem/error_message.h"
27 #include "SheafSystem/eval_family.h"
28 #include "SheafSystem/section_evaluator.h"
29 #include "SheafSystem/section_space_schema_member.h"
30 #include "SheafSystem/section_space_schema_poset.h"
31 #include "SheafSystem/sec_vd.h"
32 #include "SheafSystem/structured_block_1d.h"
33 #include "SheafSystem/structured_block_2d.h"
34 #include "SheafSystem/structured_block_3d.h"
35 
36 using namespace std;
37 using namespace unordered;
38 using namespace fiber_bundle; // Workaround for MS C++ bug.
39 
43 {
44  // Preconditions:
45 
46 
47  // Body:
48 
49  schema = 0;
50  df = 0;
51  row_dof_ct = 0;
52  evaluators = 0;
53  is_uniform = false;
54  eval_id.invalidate();
55  eval_type_id = sheaf::invalid_pod_index();
56  eval = 0;
57  eval_mbr = 0;
58  disc_to_seq_map = 0;
59  next_seq_id = 0;
60  local_id = sheaf::invalid_pod_index();
61  vertex_discretization = false;
62  correction_enabled = false;
63 
64  // Postconditions:
65 
66 
67  // Exit:
68 
69  return;
70 }
71 
75 {
76  // Don't delete schema, it belongs to someone else.
77 
78  if(evaluators != 0)
79  {
80  delete evaluators;
81  }
82 
83  eval_sp.detach_from_state();
84 
85  for(int i=1; i<eval_mbrs.ct(); ++i)
86  {
87  structured_block* lblk = eval_mbrs[i];
88  lblk->detach_from_state();
89  delete lblk;
90  }
91 
92  disc_sp.detach_from_state();
93 
94  if(disc_to_seq_map != 0)
95  {
96  delete disc_to_seq_map;
97  }
98 }
99 
101 void
104 {
105  // Preconditions:
106 
107  require(xschema.state_is_read_accessible());
108 
109  // Body:
110 
111  // Anchor features.
112 
113  // Avoid clone, initialization of schema features is expensive.
114  // schema = xschema.clone(false, false);
115 
116  schema = &xschema;
117  df = xschema.df();
118  row_dof_ct = xschema.row_dof_ct();
119 
120  base_space_host = &xschema.host()->base_space();
121 
122  // Evaluation features.
123 
124  down_set.reserve(32); // Arbitrary, but enough to avoid small reallocations.
125  visited.extend_to(base_space_host->member_index_ub().pod());
126 
127  if(evaluators == 0)
128  {
129  evaluators = eval_family::new_family(xschema.evaluator_family_name(),
130  *xschema.name_space());
131  }
132 
133  if(!eval_sp.is_attached())
134  {
135  eval_sp.attach_to_state(&xschema.evaluation());
136  }
137 
138  eval_id.invalidate();
139  eval = 0;
140 
141  if(eval_mbrs.ub() == 0)
142  {
143  eval_mbrs.reserve(4);
144  eval_mbrs[0] = 0;
145  eval_mbrs[1] = new structured_block_1d();
146  eval_mbrs[2] = new structured_block_2d();
147  eval_mbrs[3] = new structured_block_3d();
148  eval_mbrs.set_ct(4);
149  }
150 
151  eval_mbr = 0;
152 
153  // Discretization features.
154 
155  if(!disc_sp.is_attached())
156  {
157  if(xschema.evaluator_family_name() == "uniform")
158  {
161 
162  is_uniform = true;
163  disc_sp.attach_to_state(&xschema.evaluation());
164  vertex_discretization = false;
165  }
166  else
167  {
168  is_uniform = false;
169  disc_sp.attach_to_state(&xschema.discretization());
170  vertex_discretization = (disc_sp.name() == "__vertices");
171  }
172 
173  disc_to_seq_map = new unordered_map<pod_index_type, pod_index_type>();
174  }
175  else
176  {
177  disc_to_seq_map->clear();
178  }
179 
180  next_seq_id = 0;
181  local_id = 0;
182 
183  // Down set gather buffers.
184 
185  // Choose some arbitrary initial size for disc buffer.
186  // Should be large enough to avoid many small reallocations.
187 
188  const size_type ldisc_ub = 16;
189  discretization_members.reserve(ldisc_ub);
190  dofs.reserve(ldisc_ub*df);
191 
192 
193  // Discretization order correction features.
194 
195  if(correction_set.empty())
196  {
197  initialize_correction_set();
198  }
199 
200  correction_enabled = false;
201 
202  // Postconditions:
203 
204  // Exit
205 
206  return;
207 };
208 
210 void
212 initialize(const base_space_poset& xbase_space_host)
213 {
214  // Preconditions:
215 
216  require(xbase_space_host.state_is_read_accessible());
217 
218  // Body:
219 
220  // Anchor features.
221 
222  schema = 0;
223  df = 3;
224  row_dof_ct = 0;
225 
226  base_space_host = &xbase_space_host;
227 
228  // Evaluation features.
229 
230  down_set.reserve(1024); // Arbitrary, but enough to avoid small reallocations.
231  visited.extend_to(base_space_host->member_index_ub().pod());
232 
233 
234  if(evaluators == 0)
235  {
236  evaluators = eval_family::new_family("dlinear",
237  *base_space_host->name_space());
238  }
239 
240  if(!eval_sp.is_attached())
241  {
242  eval_sp.attach_to_state(&base_space_host->elements());
243  }
244 
245  eval_id.invalidate();
246  eval = 0;
247 
248  if(eval_mbrs.ub() == 0)
249  {
250  eval_mbrs.reserve(4);
251  eval_mbrs[0] = 0;
252  eval_mbrs[1] = new structured_block_1d();
253  eval_mbrs[2] = new structured_block_2d();
254  eval_mbrs[3] = new structured_block_3d();
255  eval_mbrs.set_ct(4);
256  }
257 
258  eval_mbr = 0;
259 
260  // Discretization features.
261 
262  if(!disc_sp.is_attached())
263  {
264  is_uniform = false;
265  disc_sp.attach_to_state(&base_space_host->vertices());
266  disc_to_seq_map = new unordered_map<pod_index_type, pod_index_type>();
267  vertex_discretization = true;
268  }
269  else
270  {
271  disc_to_seq_map->clear();
272  }
273 
274  next_seq_id = 0;
275  local_id = 0;
276 
277  // Down set gather buffers.
278 
279  // Choose some arbitrary initial size for disc buffer.
280  // Should be large enough to avoid many small reallocations.
281 
282  const size_type ldisc_ub = 16;
283 
284  discretization_members.reserve(ldisc_ub);
285  dofs.reserve(ldisc_ub*df);
286 
287  // Discretization order correction features.
288 
289  if(correction_set.empty())
290  {
291  initialize_correction_set();
292  }
293 
294  correction_enabled = false;
295 
296  // Postconditions:
297 
298  // Exit
299 
300  return;
301 };
302 
303 
305 void
308 {
309  // Preconditions:
310 
311  // Body:
312 
313  // The connectivity reversal trick should be applied to evaluation
314  // members which are 2D and have edges in their down set. This
315  // includes prototypes "triangle", "quad", "tri_shell", and "quad_shell".
316  // Currently only "quad" is supported in the base_space_member_prototypes
317  // poset.
318 
319  correction_set.insert(base_space_host->prototype_type_id("triangle_complex"));
320 
321  correction_set.insert(base_space_host->prototype_type_id("quad_complex"));
322 
323  // Postconditions:
324 
325 
326  // Exit:
327 
328  return;
329 };
330 
331 
333 void
336 {
337  // Preconditions:
338 
339  require(discretization_members.ct() == 2);
340 
341  // Body:
342 
343  // We assume that the current evaluator is 2-D, that its
344  // downset contains edges and vertices, and that the
345  // current discretization point is a vertex.
346  //
347  // The first evaluator to contain the edge which contains the
348  // current discretization point is the evaluator which constructed
349  // that edge, and it constructed that edge in a "positive"
350  // orientation wrt that evaluator. An edge in a 2-d space
351  // separates that space into 2 parts. So at most 1 other
352  // evaluator can share that edge and, if it exists, that evaluator
353  // views the edge as "negatively" oriented. In addition,
354  // that evaluator will be the second evaluator in the upper
355  // cover of that edge.
356 
357  // greater_index() refers to the edge containing this discretization
358  // point in the path from the current evaluator. If the current
359  // evaluator is the first evaluator in that edge's upper cover, then
360  // it constructed the edge, and the edge is in the positive orientation.
361  // Otherwise, the current evaluator did not construct the edge,
362  // the edge is negatively oriented, and the discretization member
363  // order should be reversed.
364 
365  pod_index_type first_eval =
366  base_space_host->first_cover_member(UPPER, xgreater_index.hub_pod());
367 
368  bool is_reversed = (eval_id != first_eval);
369 
370  if(is_reversed)
371  {
372  scoped_index save = discretization_members[0].disc_id;
373  discretization_members[0].disc_id = discretization_members[1].disc_id;
374  discretization_members[1].disc_id = save;
375  }
376 
377  // Postconditions:
378 
379 
380  // Exit:
381 
382  return;
383 };
384 
386 void
389 {
390  // Enable discretization order correction if possible.
391 
392  correction_enabled =
393  vertex_discretization &&
394  (correction_set.find(base_space_host->type_id(eval_id)) !=
395  correction_set.end());
396 
397 };
398 
400 void
403 {
404  // Preconditions:
405 
406  require(xindex.is_hub_scope());
407 
408  // Body:
409 
410  eval_id = xindex;
411  local_id = 0;
412  eval_type_id = base_space_host->type_id(eval_id);
413  eval = evaluators->member(eval_type_id);
414  eval_mbr = eval_mbrs[base_space_host->db(eval_id)];
415  eval_mbr->attach_to_state(base_space_host, eval_id);
416 
417  // Postconditions:
418 
419  ensure(eval_id == xindex);
420  ensure(local_id == 0);
421  ensure(eval != 0);
422  ensure(eval_mbr != 0);
423  ensure(eval_mbr->is_attached());
424 
425  // Exit:
426 
427  return;
428 }
429 
431 void
434 {
435  // Preconditions:
436 
437  require(xindex.is_hub_scope());
438 
439  // Body:
440 
441  eval_id = xindex;
442  local_id = 0;
443  eval_type_id = base_space_host->type_id(eval_id);
444  eval = evaluators->member(eval_type_id);
445 
446  // Postconditions:
447 
448  ensure(eval_id == xindex);
449  ensure(local_id == 0);
450  ensure(eval != 0);
451 
452  // Exit:
453 
454  return;
455 }
456 
458 void
461  const scoped_index& xgreater_index)
462 {
463  // Ensure there's enough room in the buffer.
464 
465  size_type lct = discretization_members.ct();
466 
467  if(lct == discretization_members.ub())
468  {
469  discretization_members.reserve(2*lct);
470  }
471 
472  // "Allocate" the next member in the buffer by incrementing the count.
473 
474  discretization_members.set_ct(lct+1);
475 
476  // Store the context in the new member;
477  // avoid an unnecessary copy by getting a reference.
478 
479  discretization_context& ldisc_context = discretization_members[lct];
480  ldisc_context.eval_id = eval_id;
481  ldisc_context.local_id = local_id;
482  ldisc_context.disc_id = xindex;
483 
484  if(correction_enabled && (discretization_members.ct() == 2))
485  {
486  ensure_discretization_order(xgreater_index);
487  }
488 }
489 
491 void
494 {
495  // Ensure there's enough room in the buffer.
496 
497  size_type lct = discretization_members.ct();
498 
499  if(lct == discretization_members.ub())
500  {
501  discretization_members.reserve(2*lct);
502  }
503 
504  // "Allocate" the next member in the buffer by incrementing the count.
505 
506  discretization_members.set_ct(lct+1);
507 
508  // Store the context in the new member;
509  // avoid an unnecessary copy by getting a reference.
510 
511  discretization_context& ldisc_context = discretization_members[lct];
512  ldisc_context.eval_id = eval_id;
513  ldisc_context.local_id = local_id;
514  ldisc_context.disc_id = xindex;
515 }
516 
518 void
520 gather_dofs(const sec_vd& xsec)
521 {
522  // Preconditions:
523 
524  require(xsec.state_is_read_accessible());
525  // require(xsec.schema().is_same_state(schema));
526 
527  // dofs ub and indexing below only correct for binary schema.
529 
530  require(dynamic_cast<const binary_section_space_schema_member*>(&xsec.schema()) != 0);
531 
532 
533  // Body:
534 
535  if(is_uniform)
536  {
539 
540  size_type ldofs_ct = row_dof_ct;
541  dofs.reserve(row_dof_ct);
542  xsec.dof_tuple(dofs.base(), row_dof_ct);
543  dofs.set_ct(row_dof_ct);
544  }
545  else
546  {
547  size_type ldisc_ct = discretization_members.ct();
548 
549  dofs.reserve(ldisc_ct*df);
550 
551  size_type ldofs_ct = 0;
552  size_type ldofs_ub = dofs.ub();
553  sec_vd::dof_type* ldofs = dofs.base();
554 
555  for(size_type i=0; i<ldisc_ct; ++i)
556  {
557  scoped_index ldisc_id = discretization_members[i].disc_id;
558  xsec.get_fiber(ldisc_id, ldofs, ldofs_ub*sizeof(sec_vd::dof_type), false);
559  ldofs += df;
560  ldofs_ct += df;
561  ldofs_ub -= df;
562  }
563 
564  dofs.set_ct(ldofs_ct);
565  }
566 
567 
568 
569  // Postconditions:
570 
571 
572  // Exit:
573 
574  return;
575 }
576 
578 void
580 gather_dofs(const sec_vd& xsec, const block<discretization_context>& xother_pts)
581 {
582  // Preconditions:
583 
584  require(xsec.state_is_read_accessible());
585  // require(xsec.schema().is_same_state(schema));
586  require_for_all(i, 0, xother_pts.ct(), disc_sp.contains_member(xother_pts[i].disc_id));
587 
589 
590  require(df <= 3);
591 
592 
593  // Body:
594 
595  size_type lother_ct = xother_pts.ct();
596  for(size_type i=0; i<lother_ct; ++i)
597  {
598  discretization_context& lcontext = xother_pts[i];
599  xsec.get_fiber(lcontext.disc_id, lcontext.values,
600  3*sizeof(sec_vd::dof_type), false);
601  }
602 
603  // Postconditions:
604 
605 
606  // Exit:
607 
608  return;
609 }
610 
611 // =============================================================================
612 // NON-MEMBER FUNCTIONS
613 // =============================================================================
614 
scoped_index eval_id
The eval member the disc member is contained in.
A context for discretization members. Intended for implementing various iterators, especially concurrent iterations over multiple sections.
scoped_index disc_id
The global index of the disc member.
void initialize(const section_space_schema_member &xschema)
Inializes an instance with schema xschema.
section_space_schema_poset * host() const
The poset which this is a handle to a component of.
size_type ct() const
The number of items currently in use.
A homogeneous collection of connected quads arranged in an i_size() x j_size() array.
void initialize_order_correction()
Previsit action for eval_sp members.
bool state_is_read_accessible() const
True if this is attached and if the state is accessible for read or access control is disabled...
void get_fiber(pod_index_type xdisc_id, vd_lite &xfiber) const
Sets xfiber to the fiber referred to by discretization id xdisc_id.
Definition: sec_vd.cc:1087
subposet & evaluation()
The evaluation subposet for section spaces on this schema (mutable version).
void gather_dofs(const sec_vd &xsec)
Gathers dofs from xsec into the dofs buffer.
STL namespace.
void set_evaluation_member(const scoped_index &xindex)
Sets eval_id to xindex, initializes local_id and eval.
virtual namespace_poset * name_space() const
The namespace of host()
A homogeneous collection of connected segments arranged in an i_size() array.
bool is_hub_scope() const
True if and only if the id space of this is the hub id space.
Definition: scoped_index.h:575
A client handle for a base space member which represents a homgeneous collection of local cells...
The lattice of closed cells of a cellular space; a lattice representation of a computational mesh...
void dof_tuple(dof_type *xbuf, int xbuflen) const
Copies the entire dof tuple into xbuf.
Definition: sec_vd.cc:847
int local_id
The local index of the disc member with respect to the eval member.
An index within the external ("client") scope of a given id space.
Definition: scoped_index.h:116
void ensure_discretization_order(const scoped_index &xgreater_index)
Ensures correct order of the discretization members.
unsigned long size_type
An unsigned integral type used to represent sizes and capacities.
Definition: sheaf.h:52
const bool UPPER
Selector for upper cover.
Definition: sheaf.h:72
static int row_dof_ct(const namespace_poset &xns, const poset_path &xpath, bool xauto_access=true)
The number of row dofs defined by the schema specified by xns and xpath. Synonym for dof_ct(xns...
void attach_to_state(const poset_state_handle *xother)
Attach this handle to the same state as xother.
std::string evaluator_family_name() const
The name of the evaluator family for section spaces on schemae hosted by this.
subposet & discretization()
The discretization subposet for section spaces on this schema (mutable version).
sec_vd_value_type values[values_ub]
The values of another section (typically the global coordinates) at this disc point.
A section of a fiber bundle with a d-dimensional vector space fiber.
Definition: sec_vd.h:54
void gather_discretization_member(const scoped_index &xindex, const scoped_index &xgreater_index)
Puts xindex into the discretization gather buffer and, if enabled, corrects discretization order...
A homogeneous collection of connected hexahedra arranged in an i_size() x j_size() x k_size() array...
virtual void detach_from_state()
Detach this handle from its state, if any.
virtual section_space_schema_member & schema()
The restricted schema for this (mutable version).
int_type pod_index_type
The plain old data index type.
Definition: pod_types.h:49
void set_and_attach_evaluation_member(const scoped_index &xindex)
Sets eval_id to xindex, initializes local_id and eval, and attaches eval_mbr.
sec_vd_dof_type dof_type
The type of degree of freedom.
Definition: sec_vd.h:91
A client handle for a poset member which has been prepared for use as a schema for a section space...
int df() const
The dimension of the fiber space component.
void initialize_correction_set()
Initializes the set of evaluation member prototypes for which the discretization member order correct...
An auto_block with a no-initialization initialization policy.
Namespace for the fiber_bundles component of the sheaf system.
SHEAF_DLL_SPEC pod_index_type invalid_pod_index()
The invalid pod index value.
Definition: pod_types.cc:31
base_space_poset & base_space()
The base space for section spaces on this schema.
pod_type hub_pod() const
The pod value of this mapped to the unglued hub id space.
Definition: scoped_index.h:710