Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FaceOffset_3 Class Reference

#include <FaceOffset_3.h>

Inheritance diagram for FaceOffset_3:
Collaboration diagram for FaceOffset_3:

Public Member Functions

 FaceOffset_3 ()
 Default constructor. More...
 
 FaceOffset_3 (Manifold *wm, COM::Window *buf)
 Construct an object from a window manifold and a buffer window. More...
 
virtual ~FaceOffset_3 ()
 
virtual double time_stepping (const COM::Attribute *spds, double dt, COM::Attribute *disps, int *smoothed=NULL)
 Main entry of the algorithm. More...
 
void set_wavefrontal_expansion (bool b)
 Set the wavefrontal switch. More...
 
bool get_wavefrontal_expansion () const
 Obtain the wavefrontal switch. More...
 
void set_normal_diffusion (char i)
 Set number of iterations for normal diffusion. More...
 
void set_feature_layer (bool b)
 Set whether or not to use feature layer. More...
 
int get_normal_diffuion () const
 Get number of iterations for normal diffusion. More...
 
void set_eigen_threshold (double eps)
 Set the threshold of eigenvalues for splitting primary and null spaces. More...
 
double get_eigen_threshold () const
 Get the threshold of eigenvalues for splitting primary and null spaces. More...
 
void set_courant_constant (double c)
 Set the constant in front of CFL condition (0<=c<1) More...
 
double get_courant_constant () const
 Get the constant in front of CFL condition (0<=c<=1) More...
 
void set_weighting_scheme (int w)
 Weighting scheme. More...
 
int get_weighting_scheme () const
 
void set_fangle_weak (double psi)
 Set the threshold for weak-feature angle. More...
 
void set_fangle_strong (double psi)
 Set the threshold for weak-feature angle. More...
 
void set_fangle_turn (double psi)
 Set the threshold for weak-feature angle. More...
 
double get_fangle_weak_radians () const
 Get the threshold for weak-feature angle. More...
 
double get_fangle_strong_radians () const
 Get the threshold for strong-feature angle. More...
 
double get_fangle_turn_radians () const
 Set the threshold for weak-feature angle. More...
 
void set_smoother (int smoother)
 Set the choice of mesh smoother. More...
 
void set_conserve (int b)
 Set mass conservation. More...
 
void reset_default_parameters (bool b=false)
 
- Public Member Functions inherited from Propagation_3
 Propagation_3 ()
 
virtual ~Propagation_3 ()
 
 Propagation_3 (Manifold *wm, COM::Window *buf)
 Construct an object from a window manifold. More...
 
virtual void set_constraints (const COM::Attribute *cnstr_types)
 Set the types and directions of nodal constraints. More...
 
void set_bounds (const COM::Attribute *bnd)
 Set the bounds. More...
 
void bound_facial_speed (COM::Attribute *fa)
 
virtual void enforce_nodal_constraints (COM::Attribute *du)
 Enforces the nodal constraints by projecting motion onto given direction. More...
 
virtual void bound_nodal_motion (COM::Attribute *disps)
 
void set_verbose (bool b)
 Set the verbose level. More...
 

Protected Member Functions

void numerical_dissipation (COM::Attribute *nodal_buffer)
 Introduce numerical dissipation into equation. More...
 
void compute_quadrics (double dt, const COM::Attribute *spds, COM::Attribute *rhs, COM::Attribute *predicted)
 Compute quadrics for every vertex. More...
 
void compute_directions (COM::Attribute *b_offset, bool in_principle)
 Compute mean normals. More...
 
void compute_volume_vector (const COM::Attribute *disps, COM::Attribute *bs)
 Compute volumn-vector. More...
 
bool obtain_constrained_directions (COM::Attribute *disps, COM::Attribute *vcenters)
 Decompose propagation directions based on constraints. More...
 
double rescale_displacements (COM::Attribute *disps, COM::Attribute *vcenters, int depth=0)
 Reduce time step based on stability limit, and rescale displacements by the reduced time step and diffusing expansion. More...
 
void filter_and_identify_ridge_edges (bool filter_curves)
 Filter out isolated ridge vertices and identify ridge edges. More...
 
void reclassify_ridge_vertices (const bool upgrade_corners, const bool upgrade_ridge, COM::Attribute *neighbor_feas, COM::Attribute *tr_attr, bool to_filter)
 
int build_ridge_neighbor_list (const COM::Attribute *maxtrnangv, const COM::Attribute *mintrnangv, const std::vector< std::map< Edge_ID, double > > &edge_maps, const COM::Attribute *maxranglev, const COM::Attribute *minranglev, const std::vector< std::map< Edge_ID, double > > &rangle_maps, std::vector< ObscendSet > &obscends)
 Build the list of ridge nighbors and obtain a list of weak-ended vertices Return the number of obscended vertices. More...
 
int append_obscure_ends (const COM::Attribute *maxtrnangv, const COM::Attribute *mintrnangv, const std::vector< std::map< Edge_ID, double > > &edge_maps, const COM::Attribute *maxranglev, const COM::Attribute *minranglev, const std::vector< std::map< Edge_ID, double > > &rangle_maps)
 
bool filter_obscended_ridge (const std::vector< std::map< Edge_ID, double > > &edge_maps, const std::vector< std::map< Edge_ID, double > > &diangl_maps, const std::vector< ObscendSet > &obscends)
 Filter out weak-ended curves. More...
 
int remove_obscure_curves (const std::vector< ObscendSet > &obscends)
 
void mark_weak_vertices ()
 Mark vertices that are weak. More...
 
void nulaplacian_smooth (const COM::Attribute *vert_normals, const COM::Attribute *tangranks, const COM::Attribute *disps, COM::Attribute *vcenters, COM::Attribute *buf, COM::Attribute *vert_weights_buf, const COM::Attribute *edge_weights=NULL)
 Redistribute smooth vertices by NuLaplacian smoothing. More...
 
void balance_mass ()
 
void distribute_volume_e2n (const COM::Attribute *fvol, const COM::Attribute *tranks, COM::Attribute *vvol)
 
void update_face_volumes (const COM::Attribute *fnormal, const COM::Attribute *vdsps, COM::Attribute *fvol)
 
void adjust_wavefrontal_motion (COM::Attribute *disps)
 
std::pair< double, double > comp_wavefrontal_motion (double det, double w, double delta, const Vector_3 &disp_nz, const Vector_3 &nrm_nz)
 
int eigen_analyze_vertex (Vector_3 A_io[3], Vector_3 &b_io, double angle_defect=0)
 
void obtain_directions (Vector_3 es[3], const Vector_3 &lambdas, int nrank, Vector_3 &b_medial, Vector_3 *b_offset=NULL) const
 
void obtain_face_offset (const Point_3 *pnts, const double *spd_ptr, const COM::Attribute *spd, double dt, const Vector_3 *dirs, COM::Element_node_enumerator &ene, Vector_3 &ns_nz, Point_3 &cnt, Vector_3 *disps, Vector_3 *ns)
 
void get_tangents (const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank, Vector_3 vs[2], double scales[2], int *is_strong=NULL) const
 
void compute_anisotropic_vertex_centers (const COM::Attribute *disps_buf)
 
void denoise_surface (const COM::Attribute *disps_buf, COM::Attribute *normal_motion)
 
void get_primary_component (const Vector_3 &nrm, const Vector_3 es[], int trank, Vector_3 &prim) const
 
int insert_boundary_edges (COM::Attribute *tr_attr)
 
void update_vertex_centers ()
 
std::pair< double, double > solve_quadratic_func (double a, double b, double c)
 
double sign (double x)
 
Vector_3 compute_weighted_normal (Vector_3 es[3], const Vector_3 &lambdas, int trank, const Vector_3 &mean_nrm, const Vector_3 &face_nrm)
 
bool is_acute_ridge (const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
 
bool is_acute_corner (const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
 
bool is_strong (const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
 
double get_nonuniform_weight (const Vector_3 &lambdas, int trank)
 
- Protected Member Functions inherited from Propagation_3
void convert_constraints (const COM::Attribute *ctypes_faces, COM::Attribute *ctypes_nodes)
 Convert facial constraints to nodal constraints. More...
 
void determine_constraint_boundary (const COM::Attribute *ctypes_faces, COM::Attribute *ctypes_bndry_edges, COM::Attribute *ctypes_bndry_nodes)
 Convert facial or panel constraints to nodal constraints. More...
 

Static Protected Member Functions

template<class FT >
static void solve (const FT &a1, const FT &a2, const FT &b1, const FT &b2, const FT &c1, const FT &c2, FT &x, FT &y)
 
template<class FT >
static void solve (const FT &a1, const FT &a2, const FT &a3, const FT &b1, const FT &b2, const FT &b3, const FT &c1, const FT &c2, const FT &c3, const FT &d1, const FT &d2, const FT &d3, FT &x, FT &y, FT &z)
 
static void solve (const Vector_3 A[3], const Vector_3 &q, Vector_3 &x)
 
static Vector_2 proj (const Vector_3 &v, const Vector_3 &d1, const Vector_3 &d2)
 
static double eval_angle (const Vector_3 &v1, const Vector_3 &v2)
 
static double eval_angle (const Vector_2 &v1, const Vector_2 &v2)
 
static void compute_eigenvectors (Vector_3 A[3], Vector_3 &lambdas)
 
- Static Protected Member Functions inherited from Propagation_3
static void get_constraint_directions (int type, int &ndirs, Vector_3 dirs[2])
 Get orthonormals of the constraints. More...
 
static void enforce_nodal_constraint (int type, Vector_3 &du)
 Enforce constraint for a specific vector. More...
 
static void bound_nodal_motion (const Point_3 &pnt, const double *bnd, Vector_3 &du, double eps=0)
 
static bool check_spherical_bound (const Point_3 &pnt, const Point_3 &org, const double rad_min, const double rad_max, double eps=0)
 
static void bound_spherical_disp (const Point_3 &pnt, const Point_3 &org, const double rad_min, const double rad_max, Vector_3 &disp, double eps=0)
 
static bool check_radial_bound (const double x, const double y, const double bnd_min, const double bnd_max, double eps=0)
 
static void bound_radial_disp (const double x, const double y, const double bnd_min, const double bnd_max, double &dx, double &dy, double eps=0)
 
static bool check_axial_bound (const double x, const double bnd_min, const double bnd_max, double eps=0)
 
static void bound_axial_disp (const double x, const double bnd_min, const double bnd_max, double &dx, double eps=0)
 
static bool reached_nodal_bound (const Point_3 &pnt, const double *bnd, double eps=0)
 
static bool in_bounding_box (const Point_3 &pnt, const Point_3 &lb, const Point_3 &ub)
 
static double square (double x)
 

Protected Attributes

bool _wf_expn
 
char _wght_scheme
 
char _nrm_dfsn
 
char _smoother
 
double _courant
 
double _inv_sqrt_c
 
double _dir_thres_weak
 
double _dir_thres_strong
 
double _tol_angle_weak
 
double _tol_angle_strong
 
int _tol_kstrong
 
double _tol_kangle
 
double _tol_eangle
 
double _tol_cos_osta
 
double _tol_turn_angle
 
double _tol_ad
 
double _eig_thres
 
double _eig_weak_lb
 
double _eig_weak_ub
 
bool _conserv
 
bool _is_strtd
 
bool _feature_layer
 
COM::Attribute * _As
 
COM::Attribute * _boffset
 
COM::Attribute * _bmedial
 
COM::Attribute * _eigvalues
 
COM::Attribute * _eigvecs
 
COM::Attribute * _vnormals
 
COM::Attribute * _facenormals
 
COM::Attribute * _facecenters
 
COM::Attribute * _faceareas
 
COM::Attribute * _vcenters
 
COM::Attribute * _tangranks
 
COM::Attribute * _ctangranks
 
COM::Attribute * _weak
 
COM::Attribute * _strong
 
COM::Attribute * _ridges
 
COM::Attribute * _ridgeneighbors
 
COM::Attribute * _scales
 
COM::Attribute * _weights
 
std::vector< std::set< Edge_ID > > _edges
 
- Protected Attributes inherited from Propagation_3
Manifold_surf
 
SURF::Access_Mode _mode
 
COM::Window * _buf
 
int _rank
 
bool _verb
 
bool _cnstr_set
 
bool _bnd_set
 
COM::Attribute * _cnstr_nodes
 
COM::Attribute * _cnstr_faces
 
COM::Attribute * _cnstr_bndry_edges
 
COM::Attribute * _cnstr_bndry_nodes
 
COM::Attribute * _cnstr_bound
 
std::vector< COM::Pane * > _panes
 

Static Protected Attributes

static const double pi = 3.14159265358979
 

Private Types

typedef std::map< Edge_ID,
std::pair< int, int > > 
ObscendSet
 

Detailed Description

Definition at line 39 of file FaceOffset_3.h.

Member Typedef Documentation

typedef std::map<Edge_ID,std::pair<int, int> > ObscendSet
private

Definition at line 40 of file FaceOffset_3.h.

Constructor & Destructor Documentation

FaceOffset_3 ( )
inline

Default constructor.

Definition at line 43 of file FaceOffset_3.h.

References reset_default_parameters().

43  : _is_strtd(0), _As(NULL), _boffset(NULL), _bmedial(NULL),
44  _eigvalues(NULL), _eigvecs(NULL), _vnormals(NULL),
45  _facenormals(NULL), _facecenters(NULL),
46  _faceareas(NULL), _vcenters(NULL), _tangranks(NULL),
47  _ctangranks(NULL), _scales(NULL), _weights(NULL)
COM::Attribute * _scales
Definition: FaceOffset_3.h:424
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
COM::Attribute * _As
Definition: FaceOffset_3.h:403
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
COM::Attribute * _faceareas
Definition: FaceOffset_3.h:414
COM::Attribute * _boffset
Definition: FaceOffset_3.h:404
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
COM::Attribute * _facecenters
Definition: FaceOffset_3.h:413
void reset_default_parameters(bool b=false)
Definition: FaceOffset_3.C:44
COM::Attribute * _bmedial
Definition: FaceOffset_3.h:405
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412
COM::Attribute * _ctangranks
Definition: FaceOffset_3.h:418

Here is the call graph for this function:

FaceOffset_3 ( Manifold wm,
COM::Window *  buf 
)

Construct an object from a window manifold and a buffer window.

Definition at line 81 of file FaceOffset_3.C.

References _As, _bmedial, _boffset, Propagation_3::_buf, _ctangranks, _eigvalues, _eigvecs, _faceareas, _facecenters, _facenormals, _is_strtd, Propagation_3::_panes, _ridgeneighbors, _ridges, _scales, _strong, _tangranks, _vcenters, _vnormals, _weak, _weights, COM_CHAR, COM_DOUBLE, COM_INT, COMMPI_Initialized(), i, MPI_MIN, reset_default_parameters(), and s.

82  : Propagation_3( wm, buf)
83 {
84  // Determine whether the mesh is structured
85  _is_strtd = true;
86  std::vector< COM::Pane*>::iterator it = _panes.begin();
87  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
88  COM::Pane *pane = *it;
89  if ( !pane->is_structured()) _is_strtd = false;
90  }
91  if ( COMMPI_Initialized()) {
92  int s = _is_strtd;
93  MPI_Allreduce( &s, &_is_strtd, 1, MPI_INT, MPI_MIN,
94  _buf->get_communicator());
95  }
96 
97  // Set parameters to default values.
99 
100  // Extend buffer window
101  _facenormals = _buf->new_attribute( "facenormals", 'e', COM_DOUBLE, 3, "");
102  _buf->resize_array( _facenormals, 0);
103 
104  _facecenters = _buf->new_attribute( "facecenters", 'e', COM_DOUBLE, 3, "");
105  _buf->resize_array( _facecenters, 0);
106 
107  _faceareas = _buf->new_attribute( "faceareas", 'e', COM_DOUBLE, 1, "");
108  _buf->resize_array( _faceareas, 0);
109 
110  // This is used to store v-center for smoothing offset.
111  _vcenters = _buf->new_attribute( "vcenters", 'n', COM_DOUBLE, 3, "");
112  _buf->resize_array( _vcenters, 0);
113 
114  _eigvalues = _buf->new_attribute( "lambda", 'n', COM_DOUBLE, 3, "");
115  _buf->resize_array( _eigvalues, 0);
116 
117  _vnormals = _buf->new_attribute( "vnormals", 'n', COM_DOUBLE, 3, "");
118  _buf->resize_array( _vnormals, 0);
119 
120  _ridges = _buf->new_attribute( "ridges", 'p', COM_INT, 2, "");
121 
122  _ridgeneighbors = _buf->new_attribute( "ridgeneighbors", 'n', COM_INT, 4, "");
123  _buf->resize_array( _ridgeneighbors, 0);
124 
125  _weak = _buf->new_attribute( "weakfeature", 'n', COM_CHAR, 1, "");
126  _buf->resize_array( _weak, 0);
127 
128  _strong = _buf->new_attribute( "strongfeature", 'n', COM_CHAR, 1, "");
129  _buf->resize_array( _strong, 0);
130 
131  _As = _buf->new_attribute( "As", 'n', COM_DOUBLE, 9, "");
132  _buf->resize_array( _As, 0);
133 
134  _boffset = _buf->new_attribute( "boffset", 'n', COM_DOUBLE, 3, "");
135  _buf->resize_array( _boffset, 0);
136 
137  _bmedial = _buf->new_attribute( "bmedial", 'n', COM_DOUBLE, 3, "");
138  _buf->resize_array( _bmedial, 0);
139 
140  _eigvecs = _buf->new_attribute( "eigvecs", 'n', COM_DOUBLE, 9, "");
141  _buf->resize_array( _eigvecs, 0);
142 
143  _tangranks = _buf->new_attribute( "tangranks", 'n', COM_CHAR, 1, "");
144  _buf->resize_array( _tangranks, 0);
145 
146  _ctangranks = _buf->new_attribute( "ctangranks", 'n', COM_CHAR, 1, "");
147  _buf->resize_array( _ctangranks, 0);
148 
149  _scales = _buf->new_attribute( "scales", 'n', COM_DOUBLE, 1, "");
150  _buf->resize_array( _scales, 0);
151 
152  _weights = _buf->new_attribute( "weights", 'n', COM_DOUBLE, 1, "");
153  _buf->resize_array( _weights, 0);
154 
155  _buf->init_done(false);
156 }
COM::Attribute * _scales
Definition: FaceOffset_3.h:424
COM::Attribute * _ridgeneighbors
Definition: FaceOffset_3.h:422
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
COM::Window * _buf
COM::Attribute * _As
Definition: FaceOffset_3.h:403
double s
Definition: blastest.C:80
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
COM::Attribute * _faceareas
Definition: FaceOffset_3.h:414
COM::Attribute * _boffset
Definition: FaceOffset_3.h:404
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_MIN
C/C++ Data types.
Definition: roccom_basic.h:129
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
COM::Attribute * _facecenters
Definition: FaceOffset_3.h:413
blockLoc i
Definition: read.cpp:79
void reset_default_parameters(bool b=false)
Definition: FaceOffset_3.C:44
COM::Attribute * _bmedial
Definition: FaceOffset_3.h:405
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
COM::Attribute * _weak
Definition: FaceOffset_3.h:419
COM::Attribute * _ridges
Definition: FaceOffset_3.h:421
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
int COMMPI_Initialized()
Definition: commpi.h:168
COM::Attribute * _strong
Definition: FaceOffset_3.h:420
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412
COM::Attribute * _ctangranks
Definition: FaceOffset_3.h:418

Here is the call graph for this function:

virtual ~FaceOffset_3 ( )
inlinevirtual

Definition at line 53 of file FaceOffset_3.h.

53 {}

Member Function Documentation

void adjust_wavefrontal_motion ( COM::Attribute *  disps)
protected
int append_obscure_ends ( const COM::Attribute *  maxtrnangv,
const COM::Attribute *  mintrnangv,
const std::vector< std::map< Edge_ID, double > > &  edge_maps,
const COM::Attribute *  maxranglev,
const COM::Attribute *  minranglev,
const std::vector< std::map< Edge_ID, double > > &  rangle_maps 
)
protected
PROP_BEGIN_NAMESPACE void balance_mass ( )
protected

Definition at line 33 of file cons_diff.C.

References Propagation_3::_buf, _faceareas, _facenormals, Propagation_3::_panes, _scales, Propagation_3::_surf, _tangranks, _vcenters, _vnormals, _weights, Rocblas::add(), COM_DOUBLE, COM_NC, Rocblas::copy(), Rocblas::copy_scalar(), distribute_volume_e2n(), Rocblas::dot(), E2N_ONE, i, j, k, and Rocblas::sub().

Referenced by obtain_constrained_directions().

33  {
34  COM::Attribute *disps =
35  _buf->new_attribute( "disps_buf_bm", 'n', COM_DOUBLE, 3, "");
36  _buf->resize_array( disps, 0);
37  COM::Attribute *pos =
38  _buf->new_attribute( "pos_buf_bm", 'n', COM_DOUBLE, 3, "");
39  _buf->resize_array( pos, 0);
40  COM::Attribute *fvol_buf =
41  _buf->new_attribute( "vfol_buf_bm", 'e', COM_DOUBLE, 1, "");
42  _buf->resize_array( fvol_buf, 0);
43  _buf->init_done( false);
44 
45  // Use face-area as buffer for facial-volume
46  COM::Attribute *fvol = _faceareas;
47 
48  // Compute volume change at each vertex.
49  const COM::Attribute *coors = _buf->attribute( COM::COM_NC);
50  Rocblas::add( coors, _vcenters, pos);
51 
52  // Obtain density-vector for vertices.
53  int normalize=false;
54  SURF::Rocsurf::compute_element_normals( _facenormals, &normalize, pos);
55  _surf->elements_to_nodes( _facenormals, disps, SURF::E2N_ONE, NULL, NULL, 1);
56 
57  // Use _scales for vortex area and _weights for vertex-volume.
58  Rocblas::dot( disps, _vnormals, _scales);
59  double zero=0;
60  Rocblas::copy_scalar( &zero, disps);
61 
62  for ( int k=0;k<2;++k) {
63  if ( k) {
64  SURF::Rocsurf::compute_swept_volumes( pos, disps, fvol);
65 
66  Rocblas::sub( fvol_buf, fvol, fvol);
67  }
68  else {
69  SURF::Rocsurf::compute_bounded_volumes( pos, coors, fvol);
70  Rocblas::copy( fvol, fvol_buf);
71  }
73 
74 
75  std::vector< COM::Pane*>::iterator it = _panes.begin();
76  // Loop through the panes and its real vertices
77  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
78  COM::Pane *pane = *it;
79 
80  const double *vs = reinterpret_cast<const double*>
81  ( pane->attribute(_weights->id())->pointer());
82  const double *as = reinterpret_cast<const double*>
83  ( pane->attribute(_scales->id())->pointer());
84  const Vector_3 *ds_m = reinterpret_cast<const Vector_3*>
85  ( pane->attribute(_vnormals->id())->pointer());
86  Vector_3 *ds = reinterpret_cast<Vector_3*>
87  ( pane->attribute(disps->id())->pointer());
88 
89  // Loop through all real nodes of the pane
90  for ( int j=0, jn=pane->size_of_real_nodes(); j<jn; ++j) {
91  ds[j] += vs[j]/as[j]*ds_m[j]; // Omit the factor 3 here
92  }
93  }
94  }
95 
97 
98  _buf->delete_attribute( fvol_buf->name());
99  _buf->delete_attribute( pos->name());
100  _buf->delete_attribute( disps->name());
101  _buf->init_done( false);
102 }
COM::Attribute * _scales
Definition: FaceOffset_3.h:424
static void sub(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for subtraction.
Definition: op3args.C:237
COM::Window * _buf
j indices k indices k
Definition: Indexing.h:6
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
COM::Attribute * _faceareas
Definition: FaceOffset_3.h:414
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
static void add(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for addition.
Definition: op3args.C:221
void distribute_volume_e2n(const COM::Attribute *fvol, const COM::Attribute *tranks, COM::Attribute *vvol)
Definition: cons_diff.C:105
blockLoc i
Definition: read.cpp:79
Manifold * _surf
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
static void copy(const Attribute *x, Attribute *y)
Wrapper for copy.
Definition: op2args.C:333
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
Some basic geometric data types.
Definition: mapbasic.h:54
static void dot(const Attribute *x, const Attribute *y, Attribute *z, const Attribute *mults=NULL)
Wrapper for dot product.
Definition: dots.C:279
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412

Here is the call graph for this function:

Here is the caller graph for this function:

int build_ridge_neighbor_list ( const COM::Attribute *  maxtrnangv,
const COM::Attribute *  mintrnangv,
const std::vector< std::map< Edge_ID, double > > &  edge_maps,
const COM::Attribute *  maxranglev,
const COM::Attribute *  minranglev,
const std::vector< std::map< Edge_ID, double > > &  rangle_maps,
std::vector< ObscendSet > &  obscends 
)
protected

Build the list of ridge nighbors and obtain a list of weak-ended vertices Return the number of obscended vertices.

Definition at line 570 of file detect_features.C.

References _edges, Propagation_3::_panes, _ridgeneighbors, _strong, Propagation_3::_surf, _tangranks, _tol_angle_strong, _tol_cos_osta, _tol_eangle, _tol_turn_angle, NTS::abs(), COM_assertion, COM_NC, Rocblas::copy_scalar(), eval_angle(), Element_node_enumerator::size_of_edges(), and RidgeNeighbor::vid.

Referenced by filter_and_identify_ridge_edges().

576  {
577 
578  COM_assertion( _panes.size()==1); // Precondition
579 
580  // Loop through the panes and ridge edges
581  Manifold::PM_iterator pm_it=_surf->pm_begin();
582  COM::Pane *pane = _panes[0];
583 
584  // Build ACH list
585  typedef std::map< int, std::list< RidgeNeighbor> > ACH_Lists;
586  ACH_Lists ach; // ACH list
587 
588  const std::set< Edge_ID> &eset_pn = _edges[0]; // List of ridge edges
589  for ( std::set< Edge_ID>::const_iterator eit=eset_pn.begin(),
590  eend=eset_pn.end(); eit!=eend; ++eit) {
591  // Make sure that eid_opp is not border
592  Edge_ID eid = *eit, eid_opp = pm_it->get_opposite_real_edge( eid);
593  COM_assertion( eset_pn.find(eid_opp)!=eset_pn.end() &&
594  !eid.is_border());
595  Element_node_enumerator ene( pane, eid.eid());
596  int lid=eid.lid(), neighbor = (lid+1)%ene.size_of_edges();
597 
598  // Fill in ridge-neighbor into _ridgeneighbors.
599  int vid = ene[lid], neighbor_id=ene[neighbor];
600  ach[vid].push_back( RidgeNeighbor( neighbor_id, eid));
601  }
602 
603  // initialize storage
604  int zero=0;
606  obscends.clear(); obscends.resize( _panes.size());
607 
608  // Check ACH list and build rdgngbs
609  RidgeNeighbor *rdgngbs = reinterpret_cast<RidgeNeighbor*>
610  ( pane->attribute(_ridgeneighbors->id())->pointer());
611  const Point_3 *pnts = reinterpret_cast<Point_3*>
612  (pane->attribute(COM_NC)->pointer());
613  const char *tranks = reinterpret_cast<char*>
614  ( pane->attribute(_tangranks->id())->pointer());
615  const double *minvs = reinterpret_cast<double*>
616  ( pane->attribute(mindianglev->id())->pointer());
617  const double *maxvs = reinterpret_cast<double*>
618  ( pane->attribute(maxdianglev->id())->pointer());
619  const double *minta = reinterpret_cast<double*>
620  (pane->attribute(mintrnangv->id())->pointer());
621  const double *maxta = reinterpret_cast<double*>
622  ( pane->attribute(maxtrnangv->id())->pointer());
623  char *strong = reinterpret_cast<char*>
624  ( pane->attribute(_strong->id())->pointer());
625  const std::map< Edge_ID, double> &diangle_pn = diangle_maps[0];
626  const std::map< Edge_ID, double> &emap_pn = edge_maps[0];
627  ObscendSet &obscend_pn = obscends[0];
628 
629  for ( ACH_Lists::iterator ach_it = ach.begin(); ach_it!=ach.end(); ++ach_it) {
630  // Check angle defect and turning angle
631  int vid= ach_it->first, index = (vid-1)*2;
632  int nedges = ach_it->second.size();
633  std::list< RidgeNeighbor>::iterator ait = ach_it->second.begin();
634 
635  if (nedges>2) {
636  // Insert into rdgngbs
637  for (; ait!=ach_it->second.end(); ) {
638  // Remove non-joint halfedges
639  Edge_ID eid = ait->eid;
640  double fangle = diangle_pn.find( eid)->second;
641  double feg = emap_pn.find( eid)->second;
642 
643  // If disjoint, then add edge into obscend_pn.
644  if ( fangle < _tol_eangle &&
645  ( strong[vid-1] || tranks[vid-1]==1 &&
646  ( (-feg < _tol_cos_osta || feg != minta[vid-1]) &&
647  ( feg < _tol_cos_osta || feg != maxta[vid-1]) ||
648  ( feg<0 || fangle != maxvs[vid-1]) &&
649  ( feg>0 || fangle != -minvs[vid-1]))) ||
650  fangle < _tol_angle_strong &&
651  ( strong[vid-1]==2 || tranks[vid-1]==1 &&
652  ( std::abs(feg) < _tol_cos_osta ||
653  feg != minta[vid-1] && feg != maxta[vid-1]) &&
654  ( feg<0 || fangle != maxvs[vid-1]) &&
655  ( feg>0 || fangle != -minvs[vid-1]))) {
656  obscend_pn[ ait->eid] = std::make_pair( vid, ait->vid);
657  ait = ach_it->second.erase( ait);
658  }
659  else
660  ++ait;
661  }
662 
663  rdgngbs[index].vid = 0; rdgngbs[index+1].vid = -1;
664  }
665 
666  // Classify dangling and semi-joint halfedges
667  ait = ach_it->second.begin();
668  if ( nedges == 1) {
669  // Insert into obscure list to indicate dangling edges
670  rdgngbs[index] = *ait; rdgngbs[index+1].vid=0;
671  Edge_ID eid = ait->eid;
672  double fangle = diangle_pn.find( eid)->second;
673 
674  if ( fangle < _tol_angle_strong || tranks[vid-1])
675  obscend_pn[ eid] = std::make_pair( ach_it->first, ait->vid);
676  }
677  else if ( nedges == 2) {
678  std::list< RidgeNeighbor>::iterator ait2 = ait; ++ait2;
679  int v1 = ait->vid, v2 = ait2->vid;
680  double fangle1 = diangle_pn.find( ait->eid)->second;
681  double fangle2 = diangle_pn.find( ait2->eid)->second;
682 
683  if ( (fangle1<_tol_angle_strong || fangle2<_tol_angle_strong) &&
684  ( !tranks[vid-1] || eval_angle
685  ( pnts[v1-1]-pnts[vid-1], pnts[vid-1]-pnts[v2-1]) > _tol_turn_angle)) {
686  // Do not insert the edges into rdgngbs but insert into obscend_pn
687  obscend_pn[ ait->eid] = std::make_pair( vid, v1);
688  obscend_pn[ ait2->eid] = std::make_pair( vid, v2);
689  }
690  else if (!rdgngbs[index+1].vid)
691  { rdgngbs[index] = *ait; rdgngbs[index+1] = *ait2; }
692  }
693  }
694 
695  int n_obscended = obscends[0].size();
696  std::cerr << "There are " << n_obscended
697  << " obscure-ended edges" << std::endl;
698  return n_obscended;
699 }
COM::Attribute * _ridgeneighbors
Definition: FaceOffset_3.h:422
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
An adaptor for enumerating node IDs of an element.
double _tol_cos_osta
Definition: FaceOffset_3.h:391
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
double _tol_angle_strong
Definition: FaceOffset_3.h:385
double _tol_eangle
Definition: FaceOffset_3.h:389
int size_of_edges() const
Number of edges per element.
std::map< Edge_ID, std::pair< int, int > > ObscendSet
Definition: FaceOffset_3.h:40
Manifold * _surf
static double eval_angle(const Vector_3 &v1, const Vector_3 &v2)
Definition: FaceOffset_3.h:323
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
std::vector< std::set< Edge_ID > > _edges
Definition: FaceOffset_3.h:427
NT abs(const NT &x)
Definition: number_utils.h:130
COM::Attribute * _strong
Definition: FaceOffset_3.h:420
double _tol_turn_angle
Definition: FaceOffset_3.h:392

Here is the call graph for this function:

Here is the caller graph for this function:

std::pair<double,double> comp_wavefrontal_motion ( double  det,
double  w,
double  delta,
const Vector_3 disp_nz,
const Vector_3 nrm_nz 
)
protected
void compute_anisotropic_vertex_centers ( const COM::Attribute *  disps_buf)
protected

Definition at line 85 of file AnisotropicSmoothing.C.

References _As, _bmedial, _facecenters, _feature_layer, Propagation_3::_panes, _strong, Propagation_3::_surf, _tangranks, _vcenters, _weights, COM_NC, Rocblas::copy_scalar(), Rocblas::div(), eigen_analyze_vertex(), eval_angle(), get_tangents(), i, j, k, min(), Element_node_enumerator::next(), nj, and Element_node_enumerator::size_of_edges().

Referenced by time_stepping().

85  {
86 
87  const double zero = 0., eps = 1.e-100;
88 
91 
92  // Loop through the panes and its real faces
93  std::vector< COM::Pane*>::iterator it = _panes.begin();
94  Manifold::PM_iterator pm_it=_surf->pm_begin();
95  for ( int i=0, local_npanes = _panes.size();
96  i<local_npanes; ++i, ++it, ++pm_it) {
97  COM::Pane *pane = *it;
98 
99  const Point_3 *pnts = reinterpret_cast<const Point_3*>
100  (pane->attribute(COM_NC)->pointer());
101  const Vector_3 *disps = nodal_disps?reinterpret_cast<const Vector_3*>
102  (pane->attribute(nodal_disps->id())->pointer()):NULL;
103  const Point_3 *fcnts = reinterpret_cast<const Point_3*>
104  ( pane->attribute(_facecenters->id())->pointer());
105  Vector_3 *vcnts = reinterpret_cast<Vector_3*>
106  ( pane->attribute(_vcenters->id())->pointer());
107  double *ws = reinterpret_cast<double*>
108  ( pane->attribute(_weights->id())->pointer());
109 
110 #if ANISOTROPIC
111  const Vector_3 *As = reinterpret_cast<const Vector_3*>
112  ( pane->attribute(_As->id())->pointer());
113  const Vector_3 *bs = reinterpret_cast<const Vector_3*>
114  ( pane->attribute(_bmedial->id())->pointer());
115 
116  const char *tranks = reinterpret_cast<const char*>
117  ( pane->attribute(_tangranks->id())->pointer());
118 
119  const char *strong = reinterpret_cast<char*>
120  ( pane->attribute(_strong->id())->pointer());
121 #endif
122 
123  // Loop through real elements of the current pane
124  Element_node_enumerator ene( pane, 1);
125  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
126  int ne = ene.size_of_edges();
127  const Point_3 &cnt = fcnts[j];
128  Vector_3 anipnt;
129 
130 #if ANISOTROPIC
131  bool has_feature=false;
132  Vector_3 Ae[3], mn; // Matrix at an edge
133 
134  // First, compute medial quadric for the face
135  Ae[0] = Ae[1] = Ae[2] = mn = Vector_3(0,0,0);
136 
137  for ( int k=0; k<ne; ++k) {
138  int vindex = ene[k]-1;
139  has_feature |= tranks[vindex]!=2;
140 
141  // Obtain the quadric at the face
142  const Vector_3 *As_v=&As[3*vindex];
143  Ae[0] += As_v[0];
144  Ae[1] += As_v[1];
145  Ae[2] += As_v[2];
146 
147  mn += bs[vindex];
148  }
149 
150  // Perform eigen-analysis
151  Vector_3 lambdas = mn;
152  int nrank = eigen_analyze_vertex( Ae, lambdas);
153 
154  Vector_3 vs_e[2];
155  double scales_e[2];
156 
157  mn = Ae[0]; nrank = 1;
158  get_tangents( Ae, lambdas, mn, nrank, vs_e, scales_e);
159 
160  Vector_3 mn_face;
161  Vector_3 vs_f[2];
162  double scales_f[2];
163  if ( has_feature) {
164  // Compute eigen-vector of weighted-sum of the tensors.
165  Ae[0] = Ae[1] = Ae[2] = Vector_3(0,0,0);
166  for ( int k=0; k<ne; ++k) {
167  int vindex = ene[k]-1;
168 
169  double w=1;
170  switch (tranks[ vindex]) {
171  case 0: {
172  w = 1.e-12;
173  break;
174  }
175  case 1: {
176  if ( strong[vindex]) {
177  w = 1.e-6;
178  break;
179  }
180  }
181  default: w = 1.;
182  }
183 
184  // Obtain the quadric at the face
185  const Vector_3 *As_v=&As[3*vindex];
186  Ae[0] += w*As_v[0];
187  Ae[1] += w*As_v[1];
188  Ae[2] += w*As_v[2];
189  }
190 
191  // Perform eigen-analysis
192  eigen_analyze_vertex( Ae, lambdas);
193  mn_face = Ae[0];
194 
195  get_tangents( Ae, lambdas, mn_face, 1, vs_f, scales_f);
196  }
197  else {
198  mn_face = Ae[0];
199 
200  scales_f[0] = scales_e[0]; scales_f[1] = scales_e[1];
201  vs_f[0] = vs_e[0]; vs_f[1] = vs_e[1];
202  }
203 #endif
204 
205  int uindex=ene[ne-1]-1, vindex=ene[0]-1;
206  // Loop through all vertices of current face.
207  for ( int k=0; k<ne; ++k) {
208  int windex = ene[(k+1==ne)?0:k+1]-1;
209 
210  Point_3 ps[3] = { pnts[uindex], pnts[vindex], pnts[windex] };
211  if ( disps) {
212  ps[0] += disps[uindex]; ps[1] += disps[vindex];
213  ps[2] += disps[windex];
214  }
215 
216 #if ANISOTROPIC
217  double scales_v[2];
218  Vector_3 vs_v[2];
219 
220  // Note: is_border node.
221  if ( _feature_layer &&
222  ( tranks[uindex]==2 || tranks[windex]==2)) {
223  scales_v[0] = scales_e[0]; scales_v[1] = scales_e[1];
224  vs_v[0] = vs_e[0]; vs_v[1] = vs_e[1];
225  }
226  else {
227  scales_v[0] = scales_f[0]; scales_v[1] = scales_f[1];
228  vs_v[0] = vs_f[0]; vs_v[1] = vs_f[1];
229  }
230 
231  const Vector_3 diff = cnt-ps[1];
232  anipnt = scales_v[0]*(diff*vs_v[0])*vs_v[0]+
233  scales_v[1]*(diff*vs_v[1])*vs_v[1];
234  if ( disps) anipnt += disps[vindex];
235 #else
236  anipnt = cnt-ps[1];
237 #endif
238 
239 #if MIN_ANGLE_WEIGHTED
240  double w = std::min( eval_angle( ps[1]-ps[0], ps[2]-ps[0]),
241  eval_angle( ps[1]-ps[2], ps[0]-ps[2]));
242 #else
243  double w=1;
244 #endif
245 
246  vcnts[vindex] += w*anipnt;
247  ws[vindex] += w;
248 
249  uindex=vindex; vindex=windex;
250  }
251  }
252  }
253 
254  _surf->reduce_on_shared_nodes( _vcenters, Manifold::OP_SUM);
255  _surf->reduce_on_shared_nodes( _weights, Manifold::OP_SUM);
257 }
An adaptor for enumerating node IDs of an element.
COM::Attribute * _As
Definition: FaceOffset_3.h:403
j indices k indices k
Definition: Indexing.h:6
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
COM::Attribute * _facecenters
Definition: FaceOffset_3.h:413
blockLoc i
Definition: read.cpp:79
COM::Attribute * _bmedial
Definition: FaceOffset_3.h:405
Manifold * _surf
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
static void div(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for division.
Definition: op3args.C:269
static double eval_angle(const Vector_3 &v1, const Vector_3 &v2)
Definition: FaceOffset_3.h:323
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54
void get_tangents(const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank, Vector_3 vs[2], double scales[2], int *is_strong=NULL) const
COM::Attribute * _strong
Definition: FaceOffset_3.h:420
bool _feature_layer
Definition: FaceOffset_3.h:401
int eigen_analyze_vertex(Vector_3 A_io[3], Vector_3 &b_io, double angle_defect=0)

Here is the call graph for this function:

Here is the caller graph for this function:

void compute_directions ( COM::Attribute *  b_offset,
bool  in_principle 
)
protected

Compute mean normals.

Definition at line 447 of file FaceOffset_3.C.

References _eigvalues, _eigvecs, Propagation_3::_panes, _tangranks, _vnormals, i, j, and obtain_directions().

Referenced by time_stepping().

447  {
448  // Loop through the panes and its real vertices
449  std::vector< COM::Pane*>::iterator it = _panes.begin();
450  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
451  COM::Pane *pane = *it;
452 
453  // Obtain pointers
454  Vector_3 *evs = reinterpret_cast<Vector_3*>
455  ( pane->attribute(_eigvecs->id())->pointer());
456  const Vector_3 *lambdas = reinterpret_cast<const Vector_3*>
457  ( pane->attribute(_eigvalues->id())->pointer());
458  Vector_3 *vnrms = reinterpret_cast<Vector_3*>
459  ( pane->attribute(_vnormals->id())->pointer());
460  Vector_3 *voffset = bo_attr ? reinterpret_cast<Vector_3*>
461  ( pane->attribute(bo_attr->id())->pointer()) : NULL;
462  const char *trank = princ ? reinterpret_cast<char*>
463  ( pane->attribute(_tangranks->id())->pointer()) : NULL;
464 
465  // Loop through all real nodes of the pane
466  for ( int j=0, jn=pane->size_of_real_nodes(); j<jn; ++j) {
467  obtain_directions( &evs[3*j], lambdas[j], princ ? 3-trank[j] : 3,
468  vnrms[j], voffset?voffset+j:NULL);
469  }
470  }
471 }
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
blockLoc i
Definition: read.cpp:79
void obtain_directions(Vector_3 es[3], const Vector_3 &lambdas, int nrank, Vector_3 &b_medial, Vector_3 *b_offset=NULL) const
Definition: FaceOffset_3.C:475
j indices j
Definition: Indexing.h:6
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
Some basic geometric data types.
Definition: mapbasic.h:54

Here is the call graph for this function:

Here is the caller graph for this function:

void compute_eigenvectors ( Vector_3  A[3],
Vector_3 lambdas 
)
staticprotected

Definition at line 572 of file quadric_analysis.C.

References COM_assertion_msg, dsyevq3(), cimg_library::cimg::info(), and swap().

Referenced by denoise_surface(), and eigen_analyze_vertex().

572  {
573 
574  double abuf[3][3] = { {A[0][0], A[0][1], A[0][2]},
575  {A[1][0], A[1][1], A[1][2]},
576  {A[2][0], A[2][1], A[2][2]}};
577  double ebuf[3][3];
578 
579  int info = dsyevq3( abuf, ebuf, &lambdas[0]);
580  COM_assertion_msg( info==0, "Computation of eigenvectos failed");
581 
582  std::swap( ebuf[0][1], ebuf[1][0]);
583  std::swap( ebuf[0][2], ebuf[2][0]);
584  std::swap( ebuf[1][2], ebuf[2][1]);
585 
586  const Vector_3 *buf = (const Vector_3*)&ebuf[0][0];
587 
588  if ( lambdas[0]<lambdas[1]) {
589  if ( lambdas[1]<lambdas[2]) { // l2>l1>l0
590  std::swap( lambdas[0], lambdas[2]);
591  A[0] = buf[2]; A[1] = buf[1]; A[2] = buf[0];
592  }
593  else {
594  double t = lambdas[0];
595  lambdas[0] = lambdas[1];
596  A[0] = buf[1];
597 
598  if ( t<lambdas[2]) { // l1>=l2>l0
599  lambdas[1] = lambdas[2]; lambdas[2] = t;
600  A[1] = buf[2]; A[2] = buf[0];
601  }
602  else { // l1>l0>=l2
603  lambdas[1] = t;
604  A[1] = buf[0]; A[2] = buf[2];
605  }
606  }
607  }
608  else if ( lambdas[0]<lambdas[2]) { // l2>l0>=l1
609  double t = lambdas[0];
610  lambdas[0] = lambdas[2]; lambdas[2] = lambdas[1]; lambdas[1] = t;
611  A[0] = buf[2]; A[1] = buf[0]; A[2] = buf[1];
612  }
613  else {
614  A[0] = buf[0];
615  if ( lambdas[1]<lambdas[2]) { // l0>=l2>l1
616  std::swap( lambdas[1], lambdas[2]);
617  A[1] = buf[2]; A[2] = buf[1];
618  }
619  else {// l0>=l1>=l2
620  A[1] = buf[1]; A[2] = buf[2];
621  }
622  }
623 }
void swap(int &a, int &b)
Definition: buildface.cpp:88
#define COM_assertion_msg(EX, msg)
int dsyevq3(double A[3][3], double Q[3][3], double w[3])
Some basic geometric data types.
Definition: mapbasic.h:54
void info()
Print informations about CImg environement variables.
Definition: CImg.h:5702

Here is the call graph for this function:

Here is the caller graph for this function:

PROP_BEGIN_NAMESPACE void compute_quadrics ( double  dt,
const COM::Attribute *  spds,
COM::Attribute *  rhs,
COM::Attribute *  predicted 
)
protected

Compute quadrics for every vertex.

Definition at line 34 of file quadric_analysis.C.

References _As, _bmedial, Propagation_3::_buf, _dir_thres_weak, _eigvalues, _eigvecs, _faceareas, _facecenters, _facenormals, _is_strtd, Propagation_3::_panes, _smoother, Propagation_3::_surf, _tangranks, _vcenters, _vnormals, _weights, _wght_scheme, angle(), COM_assertion_msg, COM_DOUBLE, COM_NC, copy, Rocblas::copy(), Rocblas::copy_scalar(), Rocblas::div(), E2N_ANGLE, E2N_AREA, E2N_ONE, eigen_analyze_vertex(), eval_angle(), i, j, k, Element_node_enumerator::next(), nj, obtain_face_offset(), pi, s, Element_node_enumerator::size_of_edges(), SMOOTHER_ANISOTROPIC, SMOOTHER_LAPLACIAN, and sqrt().

Referenced by time_stepping().

35  {
36 
37  COM_assertion_msg( spds || dt==0,
38  "If no speed function, then time step must be zero.");
39 
40  const double zero = 0., eps = 1.e-100;
41  if ( bo_attr) Rocblas::copy_scalar( &zero, bo_attr);
42  if ( dt==0) bo_attr = NULL;
43 
44  // Use the following buffer spaces: _As for matrix A; _eigvalues to
45  // store bm; _sumangles to store sum of angles
46  COM::Attribute *A_attr = _As;
47  COM::Attribute *bm_attr = _eigvalues;
48  COM::Attribute *w_attr = _weights;
49 
50  Rocblas::copy_scalar( &zero, A_attr);
51  Rocblas::copy_scalar( &zero, bm_attr);
52  Rocblas::copy_scalar( &eps, w_attr);
54 
55  COM::Attribute *sa_attr =
56  _buf->new_attribute( "sumangles", 'n', COM_DOUBLE, 1, "");
57  _buf->resize_array( sa_attr, 0);
58 
59  bool shear= _smoother==SMOOTHER_LAPLACIAN || _is_strtd ||
60  _smoother!=SMOOTHER_ANISOTROPIC && (dt==0 || bo_attr==0);
61 
62  // Loop through the panes and its real faces
63  std::vector< COM::Pane*>::iterator it = _panes.begin();
64  Manifold::PM_iterator pm_it=_surf->pm_begin();
65  for ( int i=0, local_npanes = _panes.size();
66  i<local_npanes; ++i, ++it, ++pm_it) {
67  COM::Pane *pane = *it;
68 
69  // Obtain nodal coordinates of current pane, assuming contiguous layout
70  const Point_3 *pnts = reinterpret_cast<Point_3*>
71  (pane->attribute(COM_NC)->pointer());
72  Vector_3 *fnrms = reinterpret_cast<Vector_3*>
73  ( pane->attribute(_facenormals->id())->pointer());
74  Point_3 *fcnts = reinterpret_cast<Point_3*>
75  ( pane->attribute(_facecenters->id())->pointer());
76 
77  double *ws = reinterpret_cast<double*>
78  ( pane->attribute(w_attr->id())->pointer());
79  Vector_3 *vcnts = reinterpret_cast<Vector_3*>
80  ( pane->attribute(_vcenters->id())->pointer());
81 
82  // Obtain the pointer to speed function
83  const double *spds_ptr = spds?reinterpret_cast<const double*>
84  (pane->attribute( spds->id())->pointer()):NULL;
85 
86  // Obtain pointers
87  Vector_3 *As = reinterpret_cast<Vector_3*>
88  ( pane->attribute(A_attr->id())->pointer());
89  Vector_3 *bs_m = reinterpret_cast<Vector_3*>
90  ( pane->attribute(bm_attr->id())->pointer());
91  Vector_3 *bs_o = bo_attr ? reinterpret_cast<Vector_3*>
92  ( pane->attribute(bo_attr->id())->pointer()) : NULL;
93  Vector_3 *pred_dirs = predicted ? reinterpret_cast<Vector_3*>
94  ( pane->attribute(predicted->id())->pointer()) : NULL;
95  double *sa = reinterpret_cast<double*>
96  ( pane->attribute(sa_attr->id())->pointer());
97  double *areas = reinterpret_cast<double*>
98  ( pane->attribute(_faceareas->id())->pointer());
99 
100  // Loop through real elements of the current pane
101  Element_node_enumerator ene( pane, 1);
102  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
103  // If speed is uniform within a face, then unit normal is the same
104  // after propagation.
105  Point_3 &cnt = fcnts[j];
106 
107  int ne = ene.size_of_edges();
108  int uindex=ene[ne-1]-1, vindex=ene[0]-1, windex=0;
109 
110  Vector_3 disps[9], nrms[9];
111 
112  // Compute signed distance from current face.
113  obtain_face_offset( pnts, spds_ptr, spds, dt, pred_dirs,
114  ene, fnrms[j], cnt, disps, nrms);
115 
116  double delta=0;
117  // Loop through all vertices of current face.
118  for ( int k=0; k<ne; ++k, uindex=vindex, vindex=windex) {
119  windex = ene[(k+1==ne)?0:k+1]-1;
120 
121  // Evaluate angle at each vertex.
122  Vector_3 ts[2] = { pnts[uindex]-pnts[vindex],
123  pnts[windex]-pnts[vindex]};
124  Vector_3 ns_nz = nrms[k];
125 
126  if ( bo_attr) { // Update delta
127  delta = -disps[k]*ns_nz;
128  }
129 
130  double angle = eval_angle( ts[0], ts[1]);
131  Vector_3 nrm = ns_nz;
132  double w=1;
133  if ( _wght_scheme!=SURF::E2N_ONE) {
134  switch ( _wght_scheme) {
135  case SURF::E2N_ANGLE: {
136  double s = std::sqrt((ts[0]*ts[0])*(ts[1]*ts[1]));
137  if ( s==0) w = 0;
138  else w = angle;
139 
140  break;
141  }
142  case SURF::E2N_AREA: {
143  w = areas[j]; break;
144  }
145  default: ; // w=1;
146  }
147  nrm *= w;
148  }
149 
150  // Obtain the addresses of the linear system and weight
151  Vector_3 *A_v = &As[3*vindex];
152 
153  // Update A, b_o, b_m, and as_v for the current vertex
154  A_v[0] += ns_nz[0]*nrm;
155  A_v[1] += ns_nz[1]*nrm;
156  A_v[2] += ns_nz[2]*nrm;
157 
158  if ( delta!=0) bs_o[vindex] += delta*nrm;
159  bs_m[vindex] -= nrm;
160  sa[vindex] += angle;
161 
162  if ( shear) {
163  Vector_3 diff = cnt-pnts[vindex];
164  ws[vindex] += 1.;
165  vcnts[vindex] += diff;
166  }
167  } // for k (edges)
168  } // for j (elements)
169  } // for i (panes)
170 
171  // Reduce on shared nodes for A, b_m, b_o, and r
172  _surf->reduce_on_shared_nodes( A_attr, Manifold::OP_SUM);
173  _surf->reduce_on_shared_nodes( bm_attr, Manifold::OP_SUM);
174  if ( bo_attr) _surf->reduce_on_shared_nodes( bo_attr, Manifold::OP_SUM);
175  _surf->reduce_on_shared_nodes( sa_attr, Manifold::OP_SUM);
176 
177  // Copy bm_attr into _vnormals and _bmedial
178  Rocblas::copy( bm_attr, _vnormals);
179  Rocblas::copy( bm_attr, _bmedial);
180 
181  // Reduce to maxabs so that shared nodes have exactly the same value
182  _surf->reduce_on_shared_nodes( A_attr, Manifold::OP_MAXABS);
183  _surf->reduce_on_shared_nodes( sa_attr, Manifold::OP_MAXABS);
184 
185  if ( shear) {
186  _surf->reduce_on_shared_nodes( w_attr, Manifold::OP_SUM);
187  _surf->reduce_on_shared_nodes( _vcenters, Manifold::OP_SUM);
188  // Obtain angle-weighted average of mass center at each vertex.
189  Rocblas::div( _vcenters, w_attr, _vcenters);
190  }
191 
192  // Loop through the panes and its real vertices to determine trank
193  it = _panes.begin();
194  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
195  COM::Pane *pane = *it;
196 
197  // Obtain pointers
198  Vector_3 *As = reinterpret_cast<Vector_3*>
199  ( pane->attribute(A_attr->id())->pointer());
200  Vector_3 *evs = reinterpret_cast<Vector_3*>
201  ( pane->attribute(_eigvecs->id())->pointer());
202  Vector_3 *bs_m = reinterpret_cast<Vector_3*>
203  ( pane->attribute(bm_attr->id())->pointer());
204  double *sa = reinterpret_cast<double*>
205  ( pane->attribute(sa_attr->id())->pointer());
206 
207  // Feature information
208  char *tranks = reinterpret_cast<char*>
209  ( pane->attribute(_tangranks->id())->pointer());
210 
211  // Loop through all real nodes of the pane
212  for ( int j=0, jn=pane->size_of_real_nodes(); j<jn; ++j) {
213  // Skip vertices with zero right-hand side, such as those at
214  // edge- and face-centers for quadratic elements
215  if ( bs_m[j].is_null()) continue;
216 
217  Vector_3 *A_v = &As[3*j];
218  Vector_3 *es = &evs[3*j]; // eigen-vectors of current vertex.
219  std::copy( A_v, A_v+3, es);
220 
221  // Perform eigen-analysis for the vertex using medial quadric
222  // nrank is the rank of the normal (primary) space of A.
223  char nrank = eigen_analyze_vertex( es, bs_m[j], 2*pi-sa[j]);
224 
225  // Disable features if f-angle is greater than 1.
226  if ( _dir_thres_weak>0.99) nrank=1;
227  tranks[j] = 3-nrank;
228  }
229  }
230 
231  _buf->delete_attribute( sa_attr->name());
232  _buf->init_done( false);
233 
234  // Reduce tangranks to ensure shared nodes have the same value across panes
235  _surf->reduce_on_shared_nodes( _tangranks, Manifold::OP_MIN);
236 }
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
COM::Window * _buf
An adaptor for enumerating node IDs of an element.
COM::Attribute * _As
Definition: FaceOffset_3.h:403
j indices k indices k
Definition: Indexing.h:6
void obtain_face_offset(const Point_3 *pnts, const double *spd_ptr, const COM::Attribute *spd, double dt, const Vector_3 *dirs, COM::Element_node_enumerator &ene, Vector_3 &ns_nz, Point_3 &cnt, Vector_3 *disps, Vector_3 *ns)
Definition: FaceOffset_3.C:332
#define COM_assertion_msg(EX, msg)
double s
Definition: blastest.C:80
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
COM::Attribute * _faceareas
Definition: FaceOffset_3.h:414
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
double sqrt(double d)
Definition: double.h:73
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to ** copy
Definition: roccomf90.h:20
COM::Attribute * _facecenters
Definition: FaceOffset_3.h:413
double _dir_thres_weak
Definition: FaceOffset_3.h:381
blockLoc i
Definition: read.cpp:79
double angle(Vector_3< double > v1, Vector_3< double > v2)
Compute the angle between two vectors.
Definition: geometry.C:61
COM::Attribute * _bmedial
Definition: FaceOffset_3.h:405
Manifold * _surf
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
static void div(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for division.
Definition: op3args.C:269
static double eval_angle(const Vector_3 &v1, const Vector_3 &v2)
Definition: FaceOffset_3.h:323
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
static const double pi
Definition: FaceOffset_3.h:429
static void copy(const Attribute *x, Attribute *y)
Wrapper for copy.
Definition: op2args.C:333
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412
int eigen_analyze_vertex(Vector_3 A_io[3], Vector_3 &b_io, double angle_defect=0)

Here is the call graph for this function:

Here is the caller graph for this function:

void compute_volume_vector ( const COM::Attribute *  disps,
COM::Attribute *  bs 
)
protected

Compute volumn-vector.

Vector_3 compute_weighted_normal ( Vector_3  es[3],
const Vector_3 lambdas,
int  trank,
const Vector_3 mean_nrm,
const Vector_3 face_nrm 
)
protected
void denoise_surface ( const COM::Attribute *  disps_buf,
COM::Attribute *  normal_motion 
)
protected

Definition at line 260 of file AnisotropicSmoothing.C.

References _As, Propagation_3::_cnstr_nodes, _eigvalues, _faceareas, _facecenters, Propagation_3::_panes, Propagation_3::_surf, _tangranks, _vnormals, _weak, _weights, COM_NC, compute_eigenvectors(), Rocblas::copy_scalar(), Rocblas::div(), get_nonuniform_weight(), i, j, k, nj, and offset().

Referenced by time_stepping().

261  {
262 
263  const double zero = 0., eps = 1.e-100;
264 
265  Rocblas::copy_scalar( &zero, normal_motion);
267 
268  // Loop through the panes and its real faces
269  std::vector< COM::Pane*>::iterator it = _panes.begin();
270  Manifold::PM_iterator pm_it=_surf->pm_begin();
271  for ( int i=0, local_npanes = _panes.size();
272  i<local_npanes; ++i, ++it, ++pm_it) {
273  COM::Pane *pane = *it;
274 
275  const Vector_3 *As = reinterpret_cast<const Vector_3*>
276  ( pane->attribute(_As->id())->pointer());
277  const Vector_3 *vnrms = reinterpret_cast<const Vector_3*>
278  ( pane->attribute(_vnormals->id())->pointer());
279 
280  const Point_3 *pnts = reinterpret_cast<const Point_3*>
281  (pane->attribute(COM_NC)->pointer());
282  const Vector_3 *disps = nodal_disps ? reinterpret_cast<const Vector_3*>
283  (pane->attribute(nodal_disps->id())->pointer()) : NULL;
284  const Point_3 *fcnts = reinterpret_cast<const Point_3*>
285  ( pane->attribute(_facecenters->id())->pointer());
286  const char *tranks = reinterpret_cast<const char*>
287  ( pane->attribute(_tangranks->id())->pointer());
288  const Vector_3 *lambdas = reinterpret_cast<const Vector_3*>
289  ( pane->attribute(_eigvalues->id())->pointer());
290 
291  Vector_3 *nmotion = normal_motion ? reinterpret_cast<Vector_3*>
292  ( pane->attribute(normal_motion->id())->pointer()) : NULL;
293  double *ws = normal_motion ? reinterpret_cast<double*>
294  ( pane->attribute(_weights->id())->pointer()) : NULL;
295  const double *farea = normal_motion ? reinterpret_cast<double*>
296  ( pane->attribute(_faceareas->id())->pointer()) : NULL;
297  const char *weak = reinterpret_cast<const char*>
298  ( pane->attribute(_weak->id())->pointer());
299  const int *cnstrs = _cnstr_nodes ? reinterpret_cast<const int*>
300  ( pane->attribute(_cnstr_nodes->id())->pointer()) : NULL;
301 
302  // Loop through real elements of the current pane
303  Element_node_enumerator ene( pane, 1);
304  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
305  int ne = ene.size_of_edges();
306  const Point_3 &cnt = fcnts[j];
307 
308  Vector_3 Ae[3]; // Matrix at an edge
309  Ae[0] = Ae[1] = Ae[2] = Vector_3(0,0,0);
310  bool is_weak = false;
311 
312  for ( int k=0; k<ne; ++k) {
313  int vindex = ene[k]-1;
314  if ( weak[vindex]) { is_weak = true; break; }
315  }
316  if ( !is_weak) continue;
317 
318 
319  for ( int k=0; k<ne; ++k) {
320  int vindex = ene[k]-1;
321 
322  // Obtain the quadric at the face
323  const Vector_3 *As_v=&As[3*vindex];
324 
325  double w = get_nonuniform_weight
326  ( lambdas[vindex], tranks[vindex]-(cnstrs && cnstrs[vindex]));
327 
328  Ae[0] += w*As_v[0];
329  Ae[1] += w*As_v[1];
330  Ae[2] += w*As_v[2];
331  }
332 
333  // Perform eigen-analysis to obtain diffused face normal
334  Vector_3 ls;
335  compute_eigenvectors( Ae, ls);
336  Vector_3 mn_face = Ae[0];
337 
338  for ( int k=0; k<ne; ++k) {
339  int vindex = ene[k]-1;
340 
341  if ( weak[vindex]) {
342  Vector_3 diff = (cnt-pnts[vindex]);
343  if ( disps) diff -= disps[vindex];
344 
345  double offset = diff*mn_face, cos_a=mn_face*vnrms[vindex];
346  if (cos_a<0) offset = -offset;
347 
348  // Use eigenvalue to control amount of dissipation
349  double w = farea[j];
350  double a = lambdas[vindex][1]/lambdas[vindex][0];
351  nmotion[vindex] += a*(w*offset)*vnrms[vindex];
352 
353  ws[vindex] += w;
354  }
355  }
356  }
357  }
358 
359  _surf->reduce_on_shared_nodes( normal_motion, Manifold::OP_SUM);
360  _surf->reduce_on_shared_nodes( _weights, Manifold::OP_SUM);
361  Rocblas::div( normal_motion, _weights, normal_motion);
362 }
static void compute_eigenvectors(Vector_3 A[3], Vector_3 &lambdas)
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
An adaptor for enumerating node IDs of an element.
COM::Attribute * _As
Definition: FaceOffset_3.h:403
j indices k indices k
Definition: Indexing.h:6
COM::Attribute * _cnstr_nodes
COM::Attribute * _faceareas
Definition: FaceOffset_3.h:414
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
real *8 function offset(vNorm, x2, y2, z2)
Definition: PlaneNorm.f90:211
std::vector< COM::Pane * > _panes
COM::Attribute * _facecenters
Definition: FaceOffset_3.h:413
blockLoc i
Definition: read.cpp:79
Manifold * _surf
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
static void div(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for division.
Definition: op3args.C:269
COM::Attribute * _weak
Definition: FaceOffset_3.h:419
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54
double get_nonuniform_weight(const Vector_3 &lambdas, int trank)

Here is the call graph for this function:

Here is the caller graph for this function:

void distribute_volume_e2n ( const COM::Attribute *  fvol,
const COM::Attribute *  tranks,
COM::Attribute *  vvol 
)
protected

Definition at line 105 of file cons_diff.C.

References Propagation_3::_panes, Propagation_3::_surf, Rocblas::copy_scalar(), i, j, k, Element_node_enumerator::next(), nj, and Element_node_enumerator::size_of_edges().

Referenced by balance_mass().

107  {
108 
109  double zero=0;
110  Rocblas::copy_scalar( &zero, vvol);
111 
112  // Loop through the panes and its real faces
113  std::vector< COM::Pane*>::iterator it = _panes.begin();
114  Manifold::PM_iterator pm_it=_surf->pm_begin();
115  for ( int i=0, local_npanes = _panes.size();
116  i<local_npanes; ++i, ++it, ++pm_it) {
117  COM::Pane *pane = *it;
118 
119  const double *fv = reinterpret_cast<const double*>
120  ( pane->attribute(fvol->id())->pointer());
121  double *vv = reinterpret_cast<double*>
122  ( pane->attribute(vvol->id())->pointer());
123 
124  // Loop through real elements of the current pane
125  Element_node_enumerator ene( pane, 1);
126  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
127  int ne = ene.size_of_edges();
128 
129  for (int k=0; k<ne; ++k) {
130  int index = ene[k]-1;
131  vv[index] += fv[j]; // Omit the factor 1/3 here
132  }
133  }
134  }
135 
136  // Reduce on shared nodes
137  _surf->reduce_on_shared_nodes( vvol, Manifold::OP_SUM);
138 
139 }
An adaptor for enumerating node IDs of an element.
j indices k indices k
Definition: Indexing.h:6
std::vector< COM::Pane * > _panes
blockLoc i
Definition: read.cpp:79
Manifold * _surf
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
void int * nj
Definition: read.cpp:74

Here is the call graph for this function:

Here is the caller graph for this function:

int eigen_analyze_vertex ( Vector_3  A_io[3],
Vector_3 b_io,
double  angle_defect = 0 
)
protected

Definition at line 240 of file quadric_analysis.C.

References _dir_thres_strong, _dir_thres_weak, _tol_ad, NTS::abs(), and compute_eigenvectors().

Referenced by compute_anisotropic_vertex_centers(), and compute_quadrics().

241  {
242 
243  // A_io will be replaced by its eigenvectors.
244  Vector_3 *es = A_io;
245 
246  // Create a backup of b_io, as b_io will be replaced by eigenvalues.
247  const Vector_3 b = b_io;
248  Vector_3 &lambdas = b_io;
249 
250  // Compute the eigenvalues and eigenvectors of the matrix.
251  // Note that lambdas will be in decreasing order!
252  compute_eigenvectors( es, lambdas);
253 
254  // Classify offset intersection based on acos(-b.norm()/rv) and lambdas
255  if ( std::abs(angle_defect) >= _tol_ad)
256  return 3; // Sharp corner
257  else if (lambdas[1] < _dir_thres_weak*lambdas[0])
258  return 1; // Ridge
259  else if ( lambdas[2] < _dir_thres_strong*lambdas[1])
260  return 2; // Flat
261  else // Vertices that are neither sharp nor flat, but have
262  return 4; // ambiguous ridge directions
263 }
static void compute_eigenvectors(Vector_3 A[3], Vector_3 &lambdas)
double _tol_ad
Definition: FaceOffset_3.h:393
double _dir_thres_strong
Definition: FaceOffset_3.h:382
double _dir_thres_weak
Definition: FaceOffset_3.h:381
NT abs(const NT &x)
Definition: number_utils.h:130
Some basic geometric data types.
Definition: mapbasic.h:54

Here is the call graph for this function:

Here is the caller graph for this function:

static double eval_angle ( const Vector_3 v1,
const Vector_3 v2 
)
inlinestaticprotected

Definition at line 323 of file FaceOffset_3.h.

References cimg_library::acos(), s, sqrt(), and Vector_3< Type >::squared_norm().

Referenced by build_ridge_neighbor_list(), compute_anisotropic_vertex_centers(), and compute_quadrics().

323  {
324  double sqrnrm = v1.squared_norm()*v2.squared_norm();
325  if ( sqrnrm==0) return 0;
326  double s=v1*v2/std::sqrt( sqrnrm);
327  if (s>1) s=1; else if (s<-1) s =-1;
328  return std::acos(s);
329  }
double s
Definition: blastest.C:80
double sqrt(double d)
Definition: double.h:73
Type squared_norm() const
Definition: mapbasic.h:110
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Definition: CImg.h:6051

Here is the call graph for this function:

Here is the caller graph for this function:

static double eval_angle ( const Vector_2 v1,
const Vector_2 v2 
)
inlinestaticprotected

Definition at line 331 of file FaceOffset_3.h.

References cimg_library::acos(), s, sqrt(), and Vector_2< Type >::squared_norm().

331  {
332  double sqrnrm = v1.squared_norm()*v2.squared_norm();
333  if ( sqrnrm==0) return 0;
334  double s=v1*v2/std::sqrt( sqrnrm);
335  if (s>1) s=1; else if (s<-1) s =-1;
336  return std::acos(s);
337  }
double s
Definition: blastest.C:80
double sqrt(double d)
Definition: double.h:73
Type squared_norm() const
Definition: mapbasic.h:236
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Definition: CImg.h:6051

Here is the call graph for this function:

PROP_BEGIN_NAMESPACE void filter_and_identify_ridge_edges ( bool  filter_curves)
protected

Filter out isolated ridge vertices and identify ridge edges.

Definition at line 33 of file detect_features.C.

References Propagation_3::_buf, _ctangranks, _edges, _eigvecs, _facenormals, Propagation_3::_panes, _ridges, _strong, Propagation_3::_surf, _tangranks, _tol_angle_strong, _tol_angle_weak, _tol_cos_osta, cimg_library::acos(), build_ridge_neighbor_list(), COM_assertion, COM_CHAR, COM_DOUBLE, COM_NC, COMMPI_Initialized(), Rocblas::copy(), Rocblas::copy_scalar(), filter_obscended_ridge(), i, insert_boundary_edges(), j, k, max(), n, Element_node_enumerator::next(), nj, Vector_3< Type >::normalize(), pi, reclassify_ridge_vertices(), and Element_node_enumerator::size_of_edges().

Referenced by time_stepping().

34 {
35  // Calculate boundary normals
36  _surf->update_bd_normals( _facenormals, false);
37 
38  COM::Attribute *maxdianglev =
39  _buf->new_attribute( "FO_maxdianglev", 'n', COM_DOUBLE, 1, "");
40  _buf->resize_array( maxdianglev, 0);
41 
42  double t=-pi;
43  Rocblas::copy_scalar( &t, maxdianglev);
44 
45  COM::Attribute *mindianglev =
46  _buf->new_attribute( "FO_mindianglev", 'n', COM_DOUBLE, 1, "");
47  _buf->resize_array( mindianglev, 0);
48  t=pi;
49  Rocblas::copy_scalar( &t, mindianglev);
50 
51  COM::Attribute *maxtrnangv =
52  _buf->new_attribute( "FO_maxtrnangv", 'n', COM_DOUBLE, 1, "");
53  _buf->resize_array( maxtrnangv, 0);
54 
55  t=-2;
56  Rocblas::copy_scalar( &t, maxtrnangv);
57 
58  COM::Attribute *mintrnangv =
59  _buf->new_attribute( "FO_mintrnangv", 'n', COM_DOUBLE, 1, "");
60  _buf->resize_array( mintrnangv, 0);
61  t=2;
62  Rocblas::copy_scalar( &t, mintrnangv);
63 
64  COM::Attribute *neighbor_features =
65  _buf->new_attribute( "FO_neighbor_features", 'n', COM_CHAR, 1, "");
66  _buf->resize_array( neighbor_features, 0);
67 
68  COM::Attribute *qsedges =
69  _buf->new_attribute( "FO_qsedges", 'e', COM_CHAR, 1, "");
70  _buf->resize_array( qsedges, 0);
71  _buf->init_done( false);
72 
73  int zero=0;
75 
76  // Clear ridge edges
77  _edges.clear(); _edges.resize( _panes.size());
78 
79  bool to_filter = filter_curves && _panes.size() == 1 && !COMMPI_Initialized();
80 
81  // Loop through the panes and its real faces
82  std::vector< COM::Pane*>::iterator it = _panes.begin();
83  Manifold::PM_iterator pm_it=_surf->pm_begin();
84 
85  int nedges=0, nvertices=0;
86  std::vector<std::map<Edge_ID, double> > edge_maps( _panes.size());
87  std::vector<std::map<Edge_ID, double> > diangle_maps( _panes.size());
88 
89  for ( int i=0, local_npanes = _panes.size();
90  i<local_npanes; ++i, ++it, ++pm_it) {
91  COM::Pane *pane = *it;
92  std::map< Edge_ID, double> &emap_pn = edge_maps[i];
93  std::map< Edge_ID, double> &diangle_pn = diangle_maps[i];
94 
95  nvertices += pane->size_of_real_nodes();
96 
97  // Obtain nodal coordinates of current pane, assuming contiguous layout
98  const Point_3 *pnts = reinterpret_cast<Point_3*>
99  (pane->attribute(COM_NC)->pointer());
100 
101  const Vector_3 *es = reinterpret_cast<const Vector_3*>
102  ( pane->attribute(_eigvecs->id())->pointer());
103  char *tranks = reinterpret_cast<char*>
104  ( pane->attribute(_tangranks->id())->pointer());
105  char *strong = reinterpret_cast<char*>
106  ( pane->attribute(_strong->id())->pointer());
107  double *minvs = reinterpret_cast<double*>
108  ( pane->attribute(mindianglev->id())->pointer());
109  double *maxvs = reinterpret_cast<double*>
110  ( pane->attribute(maxdianglev->id())->pointer());
111  double *minta = reinterpret_cast<double*>
112  ( pane->attribute(mintrnangv->id())->pointer());
113  double *maxta = reinterpret_cast<double*>
114  ( pane->attribute(maxtrnangv->id())->pointer());
115  Vector_3 *fnrms = reinterpret_cast<Vector_3*>
116  ( pane->attribute(_facenormals->id())->pointer());
117 
118  // Loop through real elements of the current pane
119  Element_node_enumerator ene( pane, 1);
120  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
121  int ne=ene.size_of_edges(), uindex=ene[ne-1]-1, vindex=ene[0]-1, windex=0;
122  nedges += ne;
123 
124  for ( int k=0; k<ne; ++k, uindex=vindex, vindex=windex) {
125  windex = ene[ (k+1)%ne]-1;
126 
127  Edge_ID eid(j+1,k), eid_opp = pm_it->get_opposite_real_edge( eid);
128 
129  // Consider border edges as flat and skip them when identifying ridges
130  if ( pm_it->is_physical_border_edge( eid_opp))
131  { ++nedges; continue; }
132 
133  Vector_3 tng = pnts[ windex] - pnts[vindex];
134  tng.normalize();
135  double feg = es[3*vindex+2]* tng;
136 
137  // Safeguard strong angles.
138  // Important: We assume this computation gives identical results
139  // for eid and eid_opp near the thresholds.
140  const Vector_3 &n1 = fnrms[j];
141  const Vector_3 &n2 = eid_opp.is_border() ?
142  pm_it->get_bd_normal( eid_opp) : fnrms[eid_opp.eid()-1];
143  double costheta = n1*n2;
144  if ( costheta>1) costheta = 1;
145  else if (costheta<-1) costheta = -1;
146 
147  double fangle = std::acos( costheta);
148  if ( fangle > _tol_angle_strong) {
149  // Upgrade vertices.
150  if ( tranks[vindex]==2) tranks[vindex] = 1;
151  if ( tranks[windex]==2) tranks[windex] = 1;
152 
153  if ( fangle>pi*0.505 && fangle !=pi)
154  strong[vindex] = strong[windex] = 2;
155  else
156  strong[vindex] = strong[windex] = 1;
157 
158  std::map< Edge_ID, double>::iterator rit = diangle_pn.find(eid);
159  // Make sure the fangle is used consistently.
160  if ( rit == diangle_pn.end()) diangle_pn[eid] = fangle;
161  else fangle = rit->second;
162 
163  if ( feg>0) {
164  if ( fangle > maxvs[vindex]) maxvs[vindex] = fangle;
165  if ( feg > maxta[vindex]) maxta[vindex] = feg;
166  emap_pn[ eid] = feg;
167  }
168  else {
169  if ( -fangle<minvs[vindex]) minvs[vindex] = -fangle;
170  if ( feg < minta[vindex]) minta[vindex] = feg;
171 
172  emap_pn[ eid] = feg;
173  }
174  }
175  else if ( fangle > _tol_angle_weak) {
176  if ( feg > 0) {
177  if ( fangle > maxvs[vindex]) maxvs[vindex] = fangle;
178  if ( feg > maxta[vindex]) maxta[vindex] = feg;
179  }
180  else {
181  if ( -fangle < minvs[vindex]) minvs[vindex] = -fangle;
182  if ( feg < minta[vindex]) minta[vindex] = feg;
183  }
184 
185  // Save the current edge for comparison
186  diangle_pn[eid] = fangle; emap_pn[ eid] = feg;
187  }
188  } // for k (edges)
189  } // for j (elements)
190  } // for i (panes)
191 
192  if ( to_filter)
193  std::cout << "There are " << nedges/2 << " edges and "
194  << nvertices << " vertices " << std::endl;
195 
196  // Reduce on shared nodes for mindianglev and maxdianglev
197  _surf->reduce_on_shared_nodes( mindianglev, Manifold::OP_MIN);
198  _surf->reduce_on_shared_nodes( maxdianglev, Manifold::OP_MAX);
199 
200  _surf->reduce_on_shared_nodes( mintrnangv, Manifold::OP_MIN);
201  _surf->reduce_on_shared_nodes( maxtrnangv, Manifold::OP_MAX);
202  _surf->reduce_on_shared_nodes( _strong, Manifold::OP_MAX);
203 
204  // Count the number of incident strongly attached edges.
205  it = _panes.begin();
206  pm_it=_surf->pm_begin();
207  Rocblas::copy_scalar( &zero, neighbor_features);
208 
209  for ( int i=0, local_npanes = _panes.size(); i<local_npanes;
210  ++i, ++it, ++pm_it) {
211  COM::Pane *pane = *it;
212  std::map< Edge_ID, double> &emap_pn = edge_maps[i];
213  std::map< Edge_ID, double> &diangle_pn = diangle_maps[i];
214 
215  const double *minvs = reinterpret_cast<double*>
216  ( pane->attribute(mindianglev->id())->pointer());
217  const double *maxvs = reinterpret_cast<double*>
218  ( pane->attribute(maxdianglev->id())->pointer());
219  const double *minta = reinterpret_cast<double*>
220  ( pane->attribute(mintrnangv->id())->pointer());
221  double *maxta = reinterpret_cast<double*>
222  ( pane->attribute(maxtrnangv->id())->pointer());
223 
224  char *tranks = reinterpret_cast<char*>
225  ( pane->attribute(_tangranks->id())->pointer());
226  char *nnf = reinterpret_cast<char*>
227  ( pane->attribute(neighbor_features->id())->pointer());
228 
229  COM_assertion( emap_pn.size() == diangle_pn.size());
230  // Loop through ebuf and put ridges edges onto emap_pn
231  for ( std::map< Edge_ID, double>::iterator eit=emap_pn.begin(),
232  rit=diangle_pn.begin(), eend=emap_pn.end(); eit!=eend; ++eit, ++rit) {
233  Edge_ID eid = eit->first;
234  double feg = eit->second, fangle = rit->second;
235 
236  COM_assertion(! eid.is_border());
237  Element_node_enumerator ene( pane, eid.eid());
238  int vi = eid.lid(), vindex = ene[vi]-1;
239 
240  // Determine the number of strongly attached edges
241  if ( !tranks[vindex] || tranks[vindex] == char(-1) || fangle > _tol_angle_strong ||
242  ( feg < 0 && fangle == -minvs[vindex] ||
243  feg > 0 && fangle == maxvs[vindex]) &&
244  ( feg < -_tol_cos_osta && feg == minta[vindex] ||
245  feg > _tol_cos_osta && feg == maxta[vindex])) {
246  ++nnf[vindex];
247  }
248  } // for eit
249  } // for i
250 
251  _surf->reduce_on_shared_nodes( neighbor_features, Manifold::OP_SUM);
252 
253  it = _panes.begin();
254  pm_it=_surf->pm_begin();
255 
256  for ( int i=0, local_npanes = _panes.size(); i<local_npanes;
257  ++i, ++it, ++pm_it) {
258  COM::Pane *pane = *it;
259  std::map< Edge_ID, double> &emap_pn = edge_maps[i];
260  std::map< Edge_ID, double> &diangle_pn = diangle_maps[i];
261  std::set< Edge_ID> &eset_pn = _edges[i];
262 
263  const double *minvs = reinterpret_cast<double*>
264  ( pane->attribute(mindianglev->id())->pointer());
265  const double *maxvs = reinterpret_cast<double*>
266  ( pane->attribute(maxdianglev->id())->pointer());
267  const double *minta = reinterpret_cast<double*>
268  ( pane->attribute(mintrnangv->id())->pointer());
269  double *maxta = reinterpret_cast<double*>
270  ( pane->attribute(maxtrnangv->id())->pointer());
271 
272  char *strong = reinterpret_cast<char*>
273  ( pane->attribute(_strong->id())->pointer());
274  char *tranks = reinterpret_cast<char*>
275  ( pane->attribute(_tangranks->id())->pointer());
276  char *qses = reinterpret_cast<char*>
277  ( pane->attribute(qsedges->id())->pointer());
278  char *nnf = reinterpret_cast<char*>
279  ( pane->attribute(neighbor_features->id())->pointer());
280 
281  COM_assertion( emap_pn.size() == diangle_pn.size());
282  // Loop through ebuf and put ridges edges onto emap_pn
283  for ( std::map< Edge_ID, double>::const_iterator eit=emap_pn.begin(),
284  rit=diangle_pn.begin(), eend=emap_pn.end(); eit!=eend; ++eit, ++rit) {
285  Edge_ID eid = eit->first, eid_opp = pm_it->get_opposite_real_edge( eid);
286  COM_assertion( !eid.is_border());
287  double feg = eit->second, fangle = rit->second, feg_opp;
288 
289  Element_node_enumerator ene( pane, eid.eid());
290  int vi=eid.lid(), ne = ene.size_of_edges();
291  int vindex = ene[vi]-1, windex = ene[ (vi+1)%ne]-1;
292 
293  if ( (nnf[vindex] && nnf[windex]) &&
294  ( strong[vindex] || !tranks[vindex] || tranks[vindex] == char(-1) ||
295  feg < 0 && fangle == -minvs[vindex] ||
296  feg > 0 && fangle == maxvs[vindex] ||
297  feg < -_tol_cos_osta && feg == minta[vindex] ||
298  feg > _tol_cos_osta && feg == maxta[vindex]) ||
299  nnf[vindex]==2 && nnf[windex]==2 &&
300  ( (feg_opp=emap_pn.find( eid_opp)->second)< 0 &&
301  fangle == -minvs[windex] ||
302  feg_opp > 0 && fangle == maxvs[windex]) &&
303  ( feg_opp < -_tol_cos_osta && feg_opp == minta[windex] ||
304  feg_opp > _tol_cos_osta && feg_opp == maxta[windex])) {
305  eset_pn.insert( eid);
306  qses[ eid.eid()-1] |= (1<<eid.lid());
307  }
308  } // for eit
309  } // for i
310 
311  // Update border-edge count
312  _surf->update_bdedge_bitmap( qsedges);
313 
314  // Select the edges whose both half-edges are quasi-strong.
315  it = _panes.begin();
316  pm_it=_surf->pm_begin();
317 
318  for ( int i=0, local_npanes = _panes.size(); i<local_npanes;
319  ++i, ++it, ++pm_it) {
320  std::set< Edge_ID> &eset_pn = _edges[i];
321 
322  // Select quasi-strong edges
323  for ( std::set< Edge_ID>::iterator eit=eset_pn.begin();
324  eit!=eset_pn.end();) {
325  Edge_ID eid = *eit, eid_opp = pm_it->get_opposite_real_edge( eid);
326 
327  if ( !eid_opp.is_border() && eset_pn.find(eid_opp)==eset_pn.end() ||
328  eid_opp.is_border() && !pm_it->get_bdedge_flag( eid_opp)) {
329  std::set< Edge_ID>::iterator to_delete = eit;
330  ++eit;
331  eset_pn.erase( to_delete);
332  }
333  else
334  ++eit;
335  }
336  }
337 
338  // Note: neighbor_features is used as buffers in reclassify_ridge_vertices
339  reclassify_ridge_vertices( 0, 1, neighbor_features,
340  _tangranks, to_filter);
341 
342  // Currently the filtering step does not yet work in parallel.
343  // Filter out obscure-ended ridges. Currently supports only sequential meshes
344  if ( to_filter) for ( ;;) {
345  std::vector< ObscendSet > obscends;
346 
347  int nobscended=build_ridge_neighbor_list( maxtrnangv,mintrnangv, edge_maps,
348  maxdianglev,mindianglev,
349  diangle_maps, obscends);
350  if ( nobscended==0) break;
351 
352  bool dropped = filter_obscended_ridge( edge_maps, diangle_maps, obscends);
353  if ( !dropped) break;
354 
355  reclassify_ridge_vertices( 0, 0, neighbor_features, _tangranks, 1);
356  }
357  // Reclassify ridge edges to upgrade potentially missing corners.
358  reclassify_ridge_vertices( 1, 0, neighbor_features, _tangranks, to_filter);
359 
361  // Update vertices on constraint boundary.
363  // Reclassify ridge edges to upgrade potentially missing corners.
364  reclassify_ridge_vertices(1, 1, neighbor_features, _ctangranks, to_filter);
365 
366  int nredges=0; // Number of ridge edges
367  // Export ridge edges into list
368  it = _panes.begin();
369  pm_it=_surf->pm_begin();
370  for ( int i=0, local_npanes = _panes.size();
371  i<local_npanes; ++i, ++it, ++pm_it) {
372  COM::Pane *pane = *it;
373  std::set< Edge_ID> &eset_pn = _edges[i];
374 
375  // Allocate memory for _ridges and save them.
376  COM::Attribute *att_rdg = pane->attribute(_ridges->id());
377 
378  int n=eset_pn.size();
379  att_rdg->allocate( 2, std::max(n,att_rdg->size_of_items()), 0);
380  int *rdgs = reinterpret_cast<int*>
381  ( pane->attribute(_ridges->id())->pointer()), ii=0;
382 
383  for ( std::set< Edge_ID>::const_iterator eit=eset_pn.begin();
384  eit!=eset_pn.end(); ++eit) {
385  // Make sure that eid_opp is not border
386  Edge_ID eid = *eit, eid_opp = pm_it->get_opposite_real_edge( eid);
387 
388  // Obtain vertex indices.
389  Element_node_enumerator ene( pane, eid.eid());
390  int vindex = eid.lid(), neighbor = (vindex+1)%ene.size_of_edges();
391  vindex = ene[vindex]; neighbor=ene[neighbor];
392 
393  if ( vindex<neighbor || eid_opp.is_border())
394  { rdgs[ii++] = vindex; rdgs[ii++] = neighbor; }
395  }
396 
397  att_rdg->set_size( ii/2);
398  nredges += att_rdg->size_of_items();
399  }
400 
401  if ( to_filter)
402  std::cout << "Found " << nredges << " ridge edges " << std::endl;
403 
404  // Deallocate mindianglev and maxdianglev
405  _buf->delete_attribute( qsedges->name());
406  _buf->delete_attribute( neighbor_features->name());
407  _buf->delete_attribute( mintrnangv->name());
408  _buf->delete_attribute( maxtrnangv->name());
409  _buf->delete_attribute( mindianglev->name());
410  _buf->delete_attribute( maxdianglev->name());
411  _buf->init_done( false);
412 }
COM::Window * _buf
int insert_boundary_edges(COM::Attribute *tr_attr)
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
An adaptor for enumerating node IDs of an element.
j indices k indices k
Definition: Indexing.h:6
double _tol_cos_osta
Definition: FaceOffset_3.h:391
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
C/C++ Data types.
Definition: roccom_basic.h:129
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
Vector_3 & normalize()
Definition: mapbasic.h:114
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
double _tol_angle_strong
Definition: FaceOffset_3.h:385
double _tol_angle_weak
Definition: FaceOffset_3.h:384
int size_of_edges() const
Number of edges per element.
blockLoc i
Definition: read.cpp:79
void reclassify_ridge_vertices(const bool upgrade_corners, const bool upgrade_ridge, COM::Attribute *neighbor_feas, COM::Attribute *tr_attr, bool to_filter)
Manifold * _surf
int build_ridge_neighbor_list(const COM::Attribute *maxtrnangv, const COM::Attribute *mintrnangv, const std::vector< std::map< Edge_ID, double > > &edge_maps, const COM::Attribute *maxranglev, const COM::Attribute *minranglev, const std::vector< std::map< Edge_ID, double > > &rangle_maps, std::vector< ObscendSet > &obscends)
Build the list of ridge nighbors and obtain a list of weak-ended vertices Return the number of obscen...
const NT & n
COM::Attribute * _ridges
Definition: FaceOffset_3.h:421
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
static const double pi
Definition: FaceOffset_3.h:429
std::vector< std::set< Edge_ID > > _edges
Definition: FaceOffset_3.h:427
static void copy(const Attribute *x, Attribute *y)
Wrapper for copy.
Definition: op2args.C:333
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Definition: CImg.h:6051
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54
int COMMPI_Initialized()
Definition: commpi.h:168
COM::Attribute * _strong
Definition: FaceOffset_3.h:420
bool filter_obscended_ridge(const std::vector< std::map< Edge_ID, double > > &edge_maps, const std::vector< std::map< Edge_ID, double > > &diangl_maps, const std::vector< ObscendSet > &obscends)
Filter out weak-ended curves.
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412
COM::Attribute * _ctangranks
Definition: FaceOffset_3.h:418

Here is the call graph for this function:

Here is the caller graph for this function:

bool filter_obscended_ridge ( const std::vector< std::map< Edge_ID, double > > &  edge_maps,
const std::vector< std::map< Edge_ID, double > > &  diangl_maps,
const std::vector< ObscendSet > &  obscends 
)
protected

Filter out weak-ended curves.

Definition at line 702 of file detect_features.C.

References Propagation_3::_panes, _ridgeneighbors, _strong, Propagation_3::_surf, _tangranks, _tol_kangle, _tol_kstrong, RidgeNeighbor::eid, i, remove_obscure_curves(), and RidgeNeighbor::vid.

Referenced by filter_and_identify_ridge_edges().

704  {
705  // Loop through the panes and ridge edges
706  std::vector< COM::Pane*>::iterator it = _panes.begin();
707  Manifold::PM_iterator pm_it=_surf->pm_begin();
708  int local_npanes = _panes.size();
709  std::vector< ObscendSet > todelete(local_npanes);
710 
711  for ( int i=0; i<local_npanes; ++i, ++it, ++pm_it) {
712  const ObscendSet &obscend_pn = obscends[i];
713  ObscendSet &todelete_pn = todelete[i];
714  if ( obscend_pn.empty()) continue;
715 
716  COM::Pane *pane = *it;
717  const char *tranks = reinterpret_cast<char*>
718  ( pane->attribute(_tangranks->id())->pointer());
719  char *strong = reinterpret_cast<char*>
720  ( pane->attribute(_strong->id())->pointer());
721  const RidgeNeighbor *rdgngbs = reinterpret_cast<RidgeNeighbor*>
722  ( pane->attribute(_ridgeneighbors->id())->pointer());
723  const std::map< Edge_ID, double> &diangle_pn = diangle_maps[i];
724 
725  for ( ObscendSet::const_iterator rit=obscend_pn.begin(),
726  rend=obscend_pn.end(); rit!=rend; ++rit) {
727  // Loop through edges to count
728  int cur=rit->second.first, next=rit->second.second, start=cur;
729 
730  Edge_ID eid = rit->first;
731  bool is_dangling = ( rdgngbs[ (cur-1)*2].vid==next &&
732  !rdgngbs[ (cur-1)*2+1].vid ||
733  !rdgngbs[ (cur-1)*2].vid &&
734  !rdgngbs[ (cur-1)*2+1].vid);
735  bool is_not_joint1 = ( rdgngbs[ (cur-1)*2].vid!=next &&
736  rdgngbs[ (cur-1)*2+1].vid!=next), is_not_joint2=false;
737 
738  if ( !is_dangling && !is_not_joint1) continue;
739  bool is_corner=false, is_strong1=strong[cur-1] || !tranks[cur-1];
740  bool is_strong2=strong[next-1] || !tranks[next-1];
741 
742  int count_ks = 0;
743  for ( ;!(is_corner = !tranks[next-1]) && next && next!=start; ) {
744  count_ks += diangle_pn.find( eid)->second>_tol_kangle;
745 
746  int index = (next-1)*2;
747  if ( rdgngbs[ index].vid == cur) {
748  cur = next; next = rdgngbs[index+1].vid; eid = rdgngbs[index+1].eid;
749  is_strong2=strong[next-1] || !tranks[next-1];
750  is_not_joint2 = false;
751  }
752  else {
753  Edge_ID eid_opp = pm_it->get_opposite_real_edge( eid);
754 
755  is_not_joint2 = (rdgngbs[ index+1].vid!=cur) &&
756  (obscend_pn.find(eid_opp) != obscend_pn.end());
757 
758  if ( rdgngbs[ index+1].vid == cur) {
759  cur = next; next = rdgngbs[index].vid; eid = rdgngbs[ index].eid;
760  is_strong2=strong[next-1] || !tranks[next-1];
761  }
762  else
763  { cur = next; next = 0; }
764  }
765  }
766 
767  // Check whether the edge is quasi-obscure.
768  if ( (is_dangling || is_not_joint1 && is_not_joint2) && count_ks<=_tol_kstrong ||
769  is_strong1 && is_strong2 && count_ks==0) {
770  todelete_pn.insert( *rit);
771  }
772  }
773  }
774 
775  return remove_obscure_curves( todelete);
776 }
COM::Attribute * _ridgeneighbors
Definition: FaceOffset_3.h:422
double _tol_kangle
Definition: FaceOffset_3.h:388
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
blockLoc i
Definition: read.cpp:79
std::map< Edge_ID, std::pair< int, int > > ObscendSet
Definition: FaceOffset_3.h:40
Manifold * _surf
int remove_obscure_curves(const std::vector< ObscendSet > &obscends)
COM::Attribute * _strong
Definition: FaceOffset_3.h:420

Here is the call graph for this function:

Here is the caller graph for this function:

double get_courant_constant ( ) const
inline

Get the constant in front of CFL condition (0<=c<=1)

Definition at line 87 of file FaceOffset_3.h.

References _courant.

87 { return _courant; }
double _courant
Definition: FaceOffset_3.h:378
double get_eigen_threshold ( ) const
inline

Get the threshold of eigenvalues for splitting primary and null spaces.

Definition at line 80 of file FaceOffset_3.h.

References _eig_thres.

80 { return _eig_thres; }
double _eig_thres
Definition: FaceOffset_3.h:394
double get_fangle_strong_radians ( ) const
inline

Get the threshold for strong-feature angle.

Definition at line 114 of file FaceOffset_3.h.

References _tol_angle_strong.

115  { return _tol_angle_strong; }
double _tol_angle_strong
Definition: FaceOffset_3.h:385
double get_fangle_turn_radians ( ) const
inline

Set the threshold for weak-feature angle.

Definition at line 118 of file FaceOffset_3.h.

References _tol_cos_osta, and cimg_library::acos().

119  { return std::acos(_tol_cos_osta)*2; }
double _tol_cos_osta
Definition: FaceOffset_3.h:391
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Definition: CImg.h:6051

Here is the call graph for this function:

double get_fangle_weak_radians ( ) const
inline

Get the threshold for weak-feature angle.

Definition at line 110 of file FaceOffset_3.h.

References _tol_angle_weak.

111  { return _tol_angle_weak; }
double _tol_angle_weak
Definition: FaceOffset_3.h:384
double get_nonuniform_weight ( const Vector_3 lambdas,
int  trank 
)
protected

Definition at line 47 of file AnisotropicSmoothing.C.

Referenced by denoise_surface().

47  {
48 
49  const double eps=1.e-6;
50  double w = 1/lambdas[0];
51 
52  if (trank == 2) return w;
53  else if ( trank==1 ) return eps*w;
54  else return eps*eps*w;
55 }

Here is the caller graph for this function:

int get_normal_diffuion ( ) const
inline

Get number of iterations for normal diffusion.

Definition at line 73 of file FaceOffset_3.h.

References _nrm_dfsn.

73 { return _nrm_dfsn; }
void get_primary_component ( const Vector_3 nrm,
const Vector_3  es[],
int  trank,
Vector_3 prim 
) const
inlineprotected

Definition at line 254 of file FaceOffset_3.h.

References i.

255  {
256  prim = Vector_3(0,0,0);
257 
258  for ( int i=0; i<3-trank; ++i) prim += nrm*es[i]*es[i];
259  }
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
blockLoc i
Definition: read.cpp:79
void get_tangents ( const Vector_3 es,
const Vector_3 lambdas,
const Vector_3 mn,
int  nrank,
Vector_3  vs[2],
double  scales[2],
int *  is_strong = NULL 
) const
protected

Definition at line 58 of file AnisotropicSmoothing.C.

References _dir_thres_strong, is_acute_corner(), is_acute_ridge(), max(), min(), and sqrt().

Referenced by compute_anisotropic_vertex_centers().

60  {
61  vs[0] = es[1];
62  vs[1] = es[2];
63 
64  // Bound from two ends appear to be the most robust.
65  const double max_scale=0.07, min_scale=0.005;
66 
67  if ( scales) {
68  scales[0] = std::min( max_scale, std::max(lambdas[1]/lambdas[0], min_scale));
69  scales[1] = std::min( max_scale, std::max(lambdas[2]/lambdas[0], min_scale));
70 
71  scales[0] = std::sqrt( scales[0]);
72  scales[1] = std::sqrt( scales[1]);
73 
74  if ( is_strong) {
75  bool acute_ridge = FaceOffset_3::is_acute_ridge( es, lambdas, mn, nrank);
76  bool acute_corner = FaceOffset_3::is_acute_corner( es, lambdas, mn, nrank);
77 
78  *is_strong = acute_ridge || acute_corner ||
79  lambdas[1]>_dir_thres_strong*lambdas[0];
80  }
81  }
82 }
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
double sqrt(double d)
Definition: double.h:73
bool is_strong(const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
double _dir_thres_strong
Definition: FaceOffset_3.h:382
bool is_acute_ridge(const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
Definition: FaceOffset_3.h:352
bool is_acute_corner(const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
Definition: FaceOffset_3.h:357
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346

Here is the call graph for this function:

Here is the caller graph for this function:

bool get_wavefrontal_expansion ( ) const
inline

Obtain the wavefrontal switch.

Definition at line 64 of file FaceOffset_3.h.

References _wf_expn.

64 { return _wf_expn; }
int get_weighting_scheme ( ) const
inline

Definition at line 91 of file FaceOffset_3.h.

References _wght_scheme.

91 { return _wght_scheme; }
int insert_boundary_edges ( COM::Attribute *  tr_attr)
protected

Definition at line 415 of file detect_features.C.

References Propagation_3::_buf, Propagation_3::_cnstr_bndry_edges, _edges, Propagation_3::_panes, Propagation_3::_surf, COMMPI_Initialized(), i, iend, j, k, MPI_SUM, Element_node_enumerator::next(), nj, and Element_node_enumerator::size_of_edges().

Referenced by filter_and_identify_ridge_edges().

415  {
416  std::vector< COM::Pane*>::iterator it = _panes.begin(), iend=_panes.end();
417  Manifold::PM_iterator pm_it=_surf->pm_begin();
418 
419  int inserted=0;
420  // Loop through the panes and its real elements
421  for ( int i=0; it!=iend; ++i, ++it, ++pm_it) {
422  COM::Pane *pane = *it;
423  std::set< Edge_ID> &eset_pn = _edges[i];
424 
425  char *tranks = reinterpret_cast<char*>
426  ( pane->attribute(tr_attr->id())->pointer());
427  const char *val_bndry=(const char*)pane->attribute
428  (_cnstr_bndry_edges->id())->pointer();
429 
430  // Loop through real elements of the current pane
431  Element_node_enumerator ene( pane, 1);
432  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
433  for ( int k=0, ne=ene.size_of_edges(); k<ne; ++k) {
434  Edge_ID eid(j+1,k), eid_opp = pm_it->get_opposite_real_edge( eid);
435 
436  // If a vertex has mixed geometric and topological edges,
437  // set it to be a corner
438  if ( pm_it->is_physical_border_edge( eid_opp) ||
439  (val_bndry && (val_bndry[j] & (1<<k)))) {
440  int vindex = ene[k]-1;
441 
442  if (tranks[ vindex]==2 || eset_pn.find(eid)==eset_pn.end()) {
443  if ( tranks[ vindex]==1) tranks[ vindex] = 0;
444  eset_pn.insert(eid); ++inserted;
445  }
446  }
447  } // for k
448  } // for j
449  } // for it
450 
451  int inserted_total = inserted;
452  if ( COMMPI_Initialized()) {
453  MPI_Allreduce( &inserted, &inserted_total, 1, MPI_INT, MPI_SUM,
454  _buf->get_communicator());
455  }
456 
457  return inserted_total;
458 }
COM::Window * _buf
An adaptor for enumerating node IDs of an element.
j indices k indices k
Definition: Indexing.h:6
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
std::vector< COM::Pane * > _panes
**********************************************************************Rocstar Simulation Suite Illinois Rocstar LLC All rights reserved ****Illinois Rocstar LLC IL **www illinoisrocstar com **sales illinoisrocstar com WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **Arising OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE **********************************************************************INTERFACE SUBROUTINE knode iend
blockLoc i
Definition: read.cpp:79
Manifold * _surf
COM::Attribute * _cnstr_bndry_edges
j indices j
Definition: Indexing.h:6
std::vector< std::set< Edge_ID > > _edges
Definition: FaceOffset_3.h:427
void int * nj
Definition: read.cpp:74
int COMMPI_Initialized()
Definition: commpi.h:168
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_SUM

Here is the call graph for this function:

Here is the caller graph for this function:

bool is_acute_corner ( const Vector_3 es,
const Vector_3 lambdas,
const Vector_3 mn,
int  nrank 
) const
inlineprotected

Definition at line 357 of file FaceOffset_3.h.

References NTS::abs().

Referenced by get_tangents(), and is_strong().

358  {
359 
360  return nrank==3 && ( std::abs(es[0]*mn)<=std::abs(es[1]*mn) ||
361  std::abs(es[0]*mn)<=std::abs(es[2]*mn));
362  }
NT abs(const NT &x)
Definition: number_utils.h:130

Here is the call graph for this function:

Here is the caller graph for this function:

bool is_acute_ridge ( const Vector_3 es,
const Vector_3 lambdas,
const Vector_3 mn,
int  nrank 
) const
inlineprotected

Definition at line 352 of file FaceOffset_3.h.

References NTS::abs().

Referenced by get_tangents(), and is_strong().

353  {
354  return nrank!=1 && std::abs(es[0]*mn)<=std::abs(es[1]*mn);
355  }
NT abs(const NT &x)
Definition: number_utils.h:130

Here is the call graph for this function:

Here is the caller graph for this function:

bool is_strong ( const Vector_3 es,
const Vector_3 lambdas,
const Vector_3 mn,
int  nrank 
) const
protected

Definition at line 36 of file AnisotropicSmoothing.C.

References _dir_thres_strong, is_acute_corner(), and is_acute_ridge().

37  {
38  if ( lambdas[1]>_dir_thres_strong*lambdas[0]) return true;
39 
40  return is_acute_ridge( es, lambdas, mn, nrank) ||
41  is_acute_corner( es, lambdas, mn, nrank);
42 }
double _dir_thres_strong
Definition: FaceOffset_3.h:382
bool is_acute_ridge(const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
Definition: FaceOffset_3.h:352
bool is_acute_corner(const Vector_3 *es, const Vector_3 &lambdas, const Vector_3 &mn, int nrank) const
Definition: FaceOffset_3.h:357

Here is the call graph for this function:

void mark_weak_vertices ( )
protected

Mark vertices that are weak.

Definition at line 356 of file quadric_analysis.C.

References _eig_thres, _eig_weak_lb, _eig_weak_ub, _eigvalues, Propagation_3::_panes, Propagation_3::_surf, _tangranks, _weak, Rocblas::copy_scalar(), i, j, and nj.

Referenced by time_stepping().

356  {
357  char zero_c=0;
358  Rocblas::copy_scalar( &zero_c, _weak);
359 
360  std::vector< COM::Pane*>::iterator it = _panes.begin();
361  Manifold::PM_iterator pm_it=_surf->pm_begin();
362  for ( int i=0, local_npanes = _panes.size();
363  i<local_npanes; ++i, ++it, ++pm_it) {
364  COM::Pane *pane = *it;
365  char *tranks = reinterpret_cast<char*>
366  ( pane->attribute(_tangranks->id())->pointer());
367  char *weak = reinterpret_cast<char*>
368  ( pane->attribute(_weak->id())->pointer());
369  const Vector_3 *lambdas = reinterpret_cast<const Vector_3*>
370  ( pane->attribute(_eigvalues->id())->pointer());
371 
372  for ( int j=0, nj=pane->size_of_real_nodes(); j<nj; ++j) {
373  weak[j] = tranks[j]==2 &&
374  lambdas[j][1] >= _eig_weak_lb*lambdas[j][0] &&
375  lambdas[j][1] <= _eig_weak_ub*lambdas[j][0] ||
376  tranks[j]<=1 && _eig_thres*lambdas[j][0] > lambdas[j][1];
377  }
378  }
379 
380  _surf->reduce_on_shared_nodes( _weak, Manifold::OP_MIN);
381 }
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
double _eig_weak_ub
Definition: FaceOffset_3.h:397
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
double _eig_weak_lb
Definition: FaceOffset_3.h:396
blockLoc i
Definition: read.cpp:79
Manifold * _surf
COM::Attribute * _weak
Definition: FaceOffset_3.h:419
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
double _eig_thres
Definition: FaceOffset_3.h:394
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54

Here is the call graph for this function:

Here is the caller graph for this function:

PROP_BEGIN_NAMESPACE void nulaplacian_smooth ( const COM::Attribute *  vert_normals,
const COM::Attribute *  tangranks,
const COM::Attribute *  disps,
COM::Attribute *  vcenters,
COM::Attribute *  buf,
COM::Attribute *  vert_weights_buf,
const COM::Attribute *  edge_weights = NULL 
)
protected

Redistribute smooth vertices by NuLaplacian smoothing.

Definition at line 36 of file NuLaplacian.C.

References _eigvecs, Propagation_3::_panes, Propagation_3::_surf, NTS::abs(), COM_assertion_msg, COM_NC, Rocblas::copy_scalar(), Vector_3< Type >::cross_product(), i, j, k, Element_node_enumerator::next(), nj, Vector_3< Type >::normalize(), and Element_node_enumerator::size_of_edges().

Referenced by time_stepping().

42  {
43  const double alpha = 0.03;
44 
45  // First, sum up weights for each vertex.
46  double eps = 1.e-100;
47  Rocblas::copy_scalar( &eps, vert_weights_buf);
48 
49  // Loop through the panes and its real faces
50  std::vector< COM::Pane*>::iterator it = _panes.begin();
51  for ( int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
52  COM::Pane *pane = *it;
53 
54  // Obtain address for buffer space for vertex weights
55  double *vws = reinterpret_cast<double*>
56  (pane->attribute(vert_weights_buf->id())->pointer());
57  // Obtain address for edge weights
58  const double *ews = edge_weights ? reinterpret_cast<const double*>
59  (pane->attribute(edge_weights->id())->pointer()) : NULL;
60 
61  Element_node_enumerator ene( pane, 1);
62  // Loop through the real elements of the pane
63  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
64  int ne = ene.size_of_edges();
65 
66  COM_assertion_msg( ne==4, "NuLapacian supports only quadrilateral meshes");
67 
68  // Loop through the vertices of the element to compute weights
69  for ( int k=0; k<ne; ++k) {
70  vws[ene[k]-1] += ews ? ews[j*4+k] + ews[j*4+(k+3)%4] : 1;
71  }
72  }
73  }
74  _surf->reduce_on_shared_nodes( vert_weights_buf, Manifold::OP_SUM);
75 
76  // Zero out buf
77  double zero=0;
78  Rocblas::copy_scalar( &zero, buf);
79 
80  // Loop through the panes and its real faces
81  it = _panes.begin();
82  for ( int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
83  COM::Pane *pane = *it;
84 
85  // Obtain nodal coordinates of current pane, assuming contiguous layout
86  const Vector_3 *pnts = reinterpret_cast<Vector_3*>
87  (pane->attribute(COM_NC)->pointer());
88  const Vector_3 *ds = reinterpret_cast<Vector_3*>
89  (pane->attribute(disps->id())->pointer());
90  const Vector_3 *nrms = reinterpret_cast<Vector_3*>
91  (pane->attribute(vert_normals->id())->pointer());
92  const Vector_3 *vcnt = reinterpret_cast<Vector_3*>
93  (pane->attribute(vcenters->id())->pointer());
94 
95  // Obtain address for output displacements
96  Vector_3 *dbuf = reinterpret_cast<Vector_3*>
97  (pane->attribute(buf->id())->pointer());
98  // Obtain address for buffer space for vertex weights
99  const double *vws = reinterpret_cast<const double*>
100  (pane->attribute(vert_weights_buf->id())->pointer());
101  // Obtain address for edge weights
102  const double *ews = edge_weights ? reinterpret_cast<const double*>
103  (pane->attribute(edge_weights->id())->pointer()) : NULL;
104 
105  // pnts_buf stores difference between center and perturbed position.
106  Vector_3 pnts_buf[4];
107  int is_regular[4];
108 
109  Element_node_enumerator ene( pane, 1);
110  // Loop through the real elements of the pane
111  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
112  int ne = ene.size_of_edges();
113 
114  COM_assertion_msg( ne==4,
115  "NuLapacian now supports only quadrilateral meshes");
116 
117  // Compute face center of the face perturbed along normal direction.
118  Vector_3 cnt(0,0,0);
119  for ( int k=0; k<ne; ++k) {
120  int uindex = ene[k]-1;
121 
122  is_regular[k] = std::abs(vws[uindex]-4)<1.e-6;
123  pnts_buf[k] = pnts[uindex] + ds[uindex];
124 
125  cnt += pnts_buf[k];
126  }
127  cnt *= 0.25; // Divide cnt by ne
128 
129  // pnts_buf contains the displacements from the face center to the vertex
130  for ( int k=0; k<ne; ++k) pnts_buf[k] -= cnt;
131 
132  // Loop through the edges of the element
133  int uindex=ene[ne-1]-1, vindex=ene[0]-1;
134  for ( int k=0; k<ne; ++k, uindex=vindex, vindex=ene[(k==ne)?0:k]-1) {
135  // Compute normal of the perturbed edge as the cross product
136  // of the vertex normal and edge tangent
137  Vector_3 tng = pnts[uindex]-pnts[vindex]+ vcnt[uindex]-vcnt[vindex];
138  double w = ews ? ews[j*4+k] : 0.5;
139 
140  int k_1 = (k+3)%4;
141  if ( is_regular[k_1]) {
142  // Accumulate buf and vert_weights for vertex uindex
143  Vector_3 nrm_e=Vector_3::cross_product(tng, nrms[uindex]).normalize();
144 
145  dbuf[uindex] -= w * ( pnts_buf[k_1] * nrm_e * nrm_e +
146  alpha * pnts_buf[k_1]);
147  }
148 
149  if ( is_regular[k]) {
150  // Accumulate buf and vert_weights for vertex vindex
151  Vector_3 nrm_e=Vector_3::cross_product(tng, nrms[vindex]).normalize();
152 
153  dbuf[vindex] -= w * ( pnts_buf[k] * nrm_e * nrm_e +
154  alpha * pnts_buf[k]);
155  }
156  }
157  }
158  }
159 
160  // Reduce on shared nodes for buf and vert_weights_buf
161  _surf->reduce_on_shared_nodes( buf, Manifold::OP_SUM);
162 
163  // Loop through all real vertices to update displacement vector
164  it = _panes.begin();
165  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
166  COM::Pane *pane = *it;
167 
168  const char *tranks = reinterpret_cast<const char*>
169  ( pane->attribute( tangranks->id())->pointer());
170  const double *vws = reinterpret_cast<const double*>
171  ( pane->attribute( vert_weights_buf->id())->pointer());
172 
173  Vector_3 *vcnt = reinterpret_cast<Vector_3*>
174  ( pane->attribute( vcenters->id())->pointer());
175  Vector_3 *dbuf = reinterpret_cast<Vector_3*>
176  ( pane->attribute( buf->id())->pointer());
177 
178  const Vector_3 *es = reinterpret_cast<const Vector_3*>
179  ( pane->attribute(_eigvecs->id())->pointer());
180 
181  // Loop through all real nodes of the pane
182  for ( int j=0, nj=pane->size_of_real_nodes(); j<nj; ++j) {
183  // If vertex is unmasked and is regular
184  if ( std::abs(vws[j]-4) < 1.e-6) {
185  // Assign the displacement to be the weighted average of projections
186  vcnt[j] = dbuf[j] / vws[j];
187 
188  if ( tranks[j] == 1) // Project onto the direction
189  vcnt[j] = (vcnt[j]*es[3*j+2])*es[3*j+2];
190  else if ( tranks[j] == 2) // Project onto the plane
191  vcnt[j] -= (vcnt[j]*es[3*j])*es[3*j];
192  else
193  vcnt[j] = Vector_3(0,0,0);
194  }
195  }
196  }
197 }
An adaptor for enumerating node IDs of an element.
j indices k indices k
Definition: Indexing.h:6
#define COM_assertion_msg(EX, msg)
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
Vector_3 & normalize()
Definition: mapbasic.h:114
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
blockLoc i
Definition: read.cpp:79
Manifold * _surf
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
NT abs(const NT &x)
Definition: number_utils.h:130
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54

Here is the call graph for this function:

Here is the caller graph for this function:

void numerical_dissipation ( COM::Attribute *  nodal_buffer)
protected

Introduce numerical dissipation into equation.

bool obtain_constrained_directions ( COM::Attribute *  disps,
COM::Attribute *  vcenters 
)
protected

Decompose propagation directions based on constraints.

Definition at line 506 of file FaceOffset_3.C.

References _As, _bmedial, _boffset, Propagation_3::_cnstr_bndry_nodes, Propagation_3::_cnstr_nodes, _conserv, _eig_thres, _eigvalues, _eigvecs, Propagation_3::_panes, Propagation_3::_surf, _tangranks, NTS::abs(), balance_mass(), Vector_3< Type >::cross_product(), Mesquite::det(), Propagation_3::get_constraint_directions(), i, j, k, Vector_3< Type >::normalize(), and obtain_directions().

Referenced by time_stepping().

507  {
508 
509  // Loop through the panes and its real faces
510  std::vector< COM::Pane*>::iterator it = _panes.begin();
511  Manifold::PM_iterator pm_it=_surf->pm_begin();
512 
513  const Vector_3 null_vec(0,0,0);
514 
515  // Loop through the panes and its real vertices
516  for (int i=0, local_npanes = _panes.size(); i<local_npanes; ++i, ++it) {
517  COM::Pane *pane = *it;
518 
519  // Obtain pointers
520  Vector_3 *evs = reinterpret_cast<Vector_3*>
521  ( pane->attribute(_eigvecs->id())->pointer());
522  Vector_3 *lambdas = reinterpret_cast<Vector_3*>
523  ( pane->attribute(_eigvalues->id())->pointer());
524  Vector_3 *ds = disps_buf ? reinterpret_cast<Vector_3*>
525  ( pane->attribute(disps_buf->id())->pointer()) : NULL;
526  const Vector_3 *bs = reinterpret_cast<Vector_3*>
527  ( pane->attribute(_boffset->id())->pointer());
528  const Vector_3 *bms = reinterpret_cast<Vector_3*>
529  ( pane->attribute(_bmedial->id())->pointer());
530 
531  // Feature information
532  const char *tranks = reinterpret_cast<char*>
533  ( pane->attribute(_tangranks->id())->pointer());
534  Vector_3 *vcnts = vcenters ? reinterpret_cast<Vector_3*>
535  ( pane->attribute(vcenters->id())->pointer()) : NULL;
536  const char *val_bndry_nodes = reinterpret_cast<const char*>
537  ( pane->attribute(_cnstr_bndry_nodes->id())->pointer());
538 
539  Vector_3 *As = reinterpret_cast<Vector_3*>
540  ( pane->attribute(_As->id())->pointer());
541  const int *cnstrs = _cnstr_nodes ? reinterpret_cast<int*>
542  ( pane->attribute(_cnstr_nodes->id())->pointer()) : NULL;
543 
544  // Loop through all real nodes of the pane
545  for ( int j=0, jn=pane->size_of_real_nodes(); j<jn; ++j) {
546  // Skip vertices with zero right-hand side, such as those at
547  // edge- and face-centers for quadratic elements
548  if ( lambdas[j][0]==0) continue;
549 
550  Vector_3 *es_v = &evs[3*j]; // eigen-vectors of current vertex.
551  int nrank = 3-tranks[j];
552 
553  Vector_3 V[2];
554  int ndirs = 0;
555  if ( cnstrs) get_constraint_directions( cnstrs[j], ndirs, V);
556 
557  if ( ndirs==3 ) { // Fixed point
558  lambdas[j] = es_v[0] = es_v[1] = es_v[2] = null_vec;
559 
560  if (ds) ds[j] = null_vec;
561  if (vcnts) vcnts[j] = null_vec;
562  continue;
563  }
564 
565  const Vector_3 *A_v = &As[3*j];
566  double eps = _eig_thres*lambdas[j][0];
567  // Propagate along the constrained direction.
568  double cos_fangle = 0.98481, sin_fangle = 0.17365; // (10 deg)
569 
570  if ( ds) {
571  Vector_3 b(0, 0, 0);
572  for ( int k=0; k<nrank; ++k) {
573  if ( lambdas[j][k]>eps)
574  b += ds[j]*es_v[k]*es_v[k];
575  }
576  ds[j] = b;
577  }
578 
579  if ( vcnts) { // Project tangent motion within null space
580  Vector_3 t(0, 0, 0);
581  for ( int k=1; k<3; ++k) {
582  if ( k>=nrank || lambdas[j][k]<eps)
583  // Note that vcnts may have component in domain space.
584  t += vcnts[j]*es_v[k]*es_v[k];
585  }
586  vcnts[j] = t;
587  }
588  if ( ndirs == 0) continue;
589 
590  // Evaluate surface normal
591  Vector_3 nrm_v;
592  if ( ds && ds[j]!=null_vec) {
593  nrm_v = ds[j]; nrm_v.normalize();
594  }
595  else {
596  if ( ds) ds[j] = null_vec;
597 
598  nrm_v = bms[j];
599  obtain_directions( es_v, lambdas[j], tranks[j], nrm_v);
600  }
601 
602  // Propagate along the constrained direction.
603  if ( ndirs == 2) {
604  // Split planar constraints
605  Vector_3 nrm = Vector_3::cross_product( V[0],V[1]);
606  double det = std::abs(nrm*nrm_v);
607 
608  if ( det < cos_fangle || val_bndry_nodes[j]) {
609  // Split into two directions.
610  V[0] = nrm_v; V[0] -= V[0]*nrm*nrm; V[0].normalize();
611  V[1] = Vector_3::cross_product( V[0], nrm);
612 
613  if (vcnts) vcnts[j] = vcnts[j]*V[1]*V[1];
614  }
615  else if (vcnts) { // Plane is tangent space
616  vcnts[j] -= vcnts[j]*nrm*nrm;
617 
618  if ( ds) ds[j] = null_vec;
619  continue;
620  }
621  }
622  else if ( vcnts && !val_bndry_nodes[j] &&
623  ( tranks[j]==1 && std::abs(V[0]*es_v[2]) > cos_fangle ||
624  tranks[j]==2 && std::abs(V[0]*nrm_v) < sin_fangle)) {
625  // ndir == 1
626  vcnts[j] = vcnts[j]*V[0]*V[0];
627  if ( ds) ds[j] = null_vec;
628  continue;
629  }
630 
631  if ( ds && !ds[j].is_null()) {
632  double VAV=Vector_3(V[0]*A_v[0],V[0]*A_v[1],V[0]*A_v[2])*V[0];
633  double Vb = V[0]*bs[j];
634 
635  if ( VAV<eps)
636  ds[j] = null_vec;
637  else {
638  ds[j] = (-Vb/VAV)*V[0];
639  if ( ndirs==1 && vcnts) vcnts[j] = null_vec;
640  }
641  }
642  }
643  }
644 
645  if ( _conserv && !disps_buf) balance_mass();
646 
647  return true;
648 }
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
COM::Attribute * _As
Definition: FaceOffset_3.h:403
j indices k indices k
Definition: Indexing.h:6
COM::Attribute * _cnstr_nodes
COM::Attribute * _boffset
Definition: FaceOffset_3.h:404
SURF::Vector_3< Real > Vector_3
Definition: rfc_basic.h:42
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
Vector_3 & normalize()
Definition: mapbasic.h:114
std::vector< COM::Pane * > _panes
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
blockLoc i
Definition: read.cpp:79
COM::Attribute * _bmedial
Definition: FaceOffset_3.h:405
Manifold * _surf
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
void obtain_directions(Vector_3 es[3], const Vector_3 &lambdas, int nrank, Vector_3 &b_medial, Vector_3 *b_offset=NULL) const
Definition: FaceOffset_3.C:475
double det(const Matrix3D &A)
j indices j
Definition: Indexing.h:6
double _eig_thres
Definition: FaceOffset_3.h:394
COM::Attribute * _cnstr_bndry_nodes
NT abs(const NT &x)
Definition: number_utils.h:130
static void get_constraint_directions(int type, int &ndirs, Vector_3 dirs[2])
Get orthonormals of the constraints.
Some basic geometric data types.
Definition: mapbasic.h:54
void balance_mass()
Definition: cons_diff.C:33

Here is the call graph for this function:

Here is the caller graph for this function:

void obtain_directions ( Vector_3  es[3],
const Vector_3 lambdas,
int  nrank,
Vector_3 b_medial,
Vector_3 b_offset = NULL 
) const
protected

Definition at line 475 of file FaceOffset_3.C.

References _eig_thres, k, and Vector_3< Type >::normalize().

Referenced by compute_directions(), and obtain_constrained_directions().

477 {
478  // Use smaller threshold for acute angles.
479  double eps = lambdas[0]*_eig_thres;
480 
481  if ( b_offset) {
482  // Solve for x within primary space
483  Vector_3 d_offset(0,0,0);
484  for ( int k=0; k<nrank; ++k) {
485  if ( lambdas[k]>eps) {
486  d_offset += (es[k]* *b_offset/-lambdas[k])*es[k];
487  }
488  }
489 
490  *b_offset = d_offset;
491  }
492 
493  // Solve for x within primary space
494  Vector_3 d_medial(0,0,0);
495  for ( int k=0; k<nrank; ++k) {
496  if ( lambdas[k]>eps) {
497  d_medial += (es[k] * b_medial/-lambdas[k])*es[k];
498  }
499  }
500 
501  b_medial = d_medial.normalize();
502 }
j indices k indices k
Definition: Indexing.h:6
Vector_3 & normalize()
Definition: mapbasic.h:114
double _eig_thres
Definition: FaceOffset_3.h:394
Some basic geometric data types.
Definition: mapbasic.h:54

Here is the call graph for this function:

Here is the caller graph for this function:

void obtain_face_offset ( const Point_3 pnts,
const double *  spd_ptr,
const COM::Attribute *  spd,
double  dt,
const Vector_3 dirs,
COM::Element_node_enumerator &  ene,
Vector_3 ns_nz,
Point_3 cnt,
Vector_3 disps,
Vector_3 ns 
)
protected

Definition at line 332 of file FaceOffset_3.C.

References NTS::abs(), COM_assertion_msg, Vector_3< Type >::cross_product(), d, i, Element_node_enumerator::id(), Attribute::is_elemental(), Attribute::is_nodal(), k, Vector_3< Type >::norm(), Vector_3< Type >::normalize(), Element_node_vectors_k_const< Value >::set(), Attribute::size_of_components(), and Element_node_enumerator::size_of_edges().

Referenced by compute_quadrics().

336  {
337 
338  const Vector_3 null_vec(0,0,0);
339  int ne=ene.size_of_edges();
340 
341  // Evaluate current face normal
342  Element_node_vectors_k_const<Point_3> ps; ps.set( pnts, ene, 1);
343  SURF::Generic_element_2 e(ne);
344  Point_3 pnts_buf[9];
345 
346  // Compute new position for all vertices
347  int ncomp = spd?spd->size_of_components():0;
348  COM_assertion_msg( !ncomp || ncomp==1 && spd->is_elemental() ||
349  ncomp==3 && spd->is_nodal(),
350  "Speed must be scalar-elemental or 3-vector-nodal");
351 
352  // Copy coordinates into buffer.
353  for ( int i=0; i<ne; ++i) pnts_buf[i] = ps[i];
354 
355  // If dirs is present, then compute the displacement
356  if ( dt!=0 && ncomp==3) { // Add dt*speed to each point
357  for ( int i=0; i<ne; ++i)
358  pnts_buf[i] += disps[i] = dt*((const Vector_3*)spd_ptr)[ene[i]-1];
359  }
360  else if ( dt==0) {
361  for ( int i=0; i<ne; ++i) disps[i] = null_vec;
362  }
363 
364  // Offset face normal equal to current face normal
365  e.interpolate_to_center((Vector_3*)pnts_buf, (Vector_3*)&cnt);
366 
367  // Compute normal directions.
368  Vector_2 nc(0.5,0.5);
369  Vector_3 J[2];
370  e.Jacobian( pnts_buf, nc, J);
371  ns_nz = Vector_3::cross_product( J[0], J[1]).normalize();
372 
373  if ( ne==3) {
374  ns[0] = ns[1] = ns[2] = ns_nz;
375  }
376  else {
377  for ( int k=0; k<ne; ++k) {
378  Vector_3 ts[] = { pnts_buf[(k+1)%ne]-pnts_buf[k],
379  pnts_buf[(k+ne-1)%ne]-pnts_buf[k]};
380  ns[k] = Vector_3::cross_product( ts[0], ts[1]);
381 
382  // If the angle is far from 180 or 0 degrees, then use triangle's normal
383  double l = ns[k].norm();
384  if ( l > std::abs(0.05*ts[0]*ts[1])) ns[k] /= l;
385  else ns[k] = ns_nz;
386  }
387  }
388 
389  // Compute points for normal motion.
390  if (dt!=0 && ncomp==1) {
391  double l = dt*spd_ptr[ene.id()-1];
392  Vector_3 d = l*ns_nz;
393  (Vector_3&)cnt += l*ns_nz;
394 
395  if ( ne==3) {
396  for ( int k=0; k<ne; ++k) pnts_buf[k] += (disps[k] = d);
397  }
398  else {
399  for ( int k=0; k<ne; ++k) pnts_buf[k] += (disps[k] = l * ns[k]);
400  }
401  }
402 
403  // If wave-frontal motion, recalculate the directions and displacements.
404  if ( dirs) {
405  for ( int i=0; i<ne; ++i) {
406  int vindex= ene[i]-1;
407 
408  if ( dirs[vindex].is_null()) {
409  disps[i] = null_vec;
410  pnts_buf[i] = ps[i] + disps[i];
411  }
412  else {
413  Vector_3 dir = dirs[vindex];
414  dir.normalize();
415 
416  Vector_3 tng = ( pnts_buf[(i+ne-1)%ne] - pnts_buf[i]) +
417  (pnts_buf[(i+1)%ne] - pnts_buf[i]);
418 
419  if ( tng * dir < 0) { // Expansion
420  double l = (disps[i] * ns[i]);
421  if ( dir * ns[i]<0) l=-l;
422 
423  (disps[i] = dir) *= l;
424 
425  pnts_buf[i] = ps[i] + disps[i];
426  }
427  }
428  }
429 
430  // Reevaluate normal directions.
431  e.Jacobian( pnts_buf, nc, J);
432  ns_nz = Vector_3::cross_product( J[0], J[1]).normalize();
433 
434  if ( ne==3) {
435  ns[0] = ns[1] = ns[2] = ns_nz;
436  }
437  else {
438  for ( int k=0; k<ne; ++k) {
440  ( pnts_buf[(k+1)%ne]-pnts_buf[k],
441  pnts_buf[(k+ne-1)%ne]-pnts_buf[k]).normalize();
442  }
443  }
444  }
445 }
const NT & d
j indices k indices k
Definition: Indexing.h:6
#define COM_assertion_msg(EX, msg)
Vector_3 & normalize()
Definition: mapbasic.h:114
This is a helper class for accessing nodal data.
blockLoc i
Definition: read.cpp:79
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
void set(const Value *p, Element_node_enumerator &ene, int strd)
initialize the accessor with a pointer and a specific stride.
NT abs(const NT &x)
Definition: number_utils.h:130
Some basic geometric data types.
Definition: mapbasic.h:54
Type norm() const
Definition: mapbasic.h:112

Here is the call graph for this function:

Here is the caller graph for this function:

static Vector_2 proj ( const Vector_3 v,
const Vector_3 d1,
const Vector_3 d2 
)
inlinestaticprotected

Definition at line 318 of file FaceOffset_3.h.

319  {
320  return Vector_2( v*d1, v*d2);
321  }
SURF::Vector_2< Real > Vector_2
Definition: rfc_basic.h:44
void reclassify_ridge_vertices ( const bool  upgrade_corners,
const bool  upgrade_ridge,
COM::Attribute *  neighbor_feas,
COM::Attribute *  tr_attr,
bool  to_filter 
)
protected

Definition at line 461 of file detect_features.C.

References Propagation_3::_buf, _edges, Propagation_3::_panes, Propagation_3::_surf, _tol_cos_osta, NTS::abs(), COM_assertion, COM_DOUBLE, COM_NC, Rocblas::copy_scalar(), j, nj, and Vector_3< Type >::normalize().

Referenced by filter_and_identify_ridge_edges().

465  {
466 
467  COM::Attribute *vecsums_buf = NULL;
468  if ( upgrade_corners) {
469  vecsums_buf = _buf->new_attribute( "FO_vecsums_buf", 'n', COM_DOUBLE, 3, "");
470  _buf->resize_array( vecsums_buf, 0);
471  }
472 
473  int zero=0;
474  Rocblas::copy_scalar( &zero, neighbor_feas);
475 
476  Vector_3 *pnts=NULL, *vss=NULL;
477  // Loop through the panes and the candidate edges to count incident edges
478  std::vector< COM::Pane*>::iterator it = _panes.begin();
479  Manifold::PM_iterator pm_it=_surf->pm_begin();
480  for ( int ii=0, local_npanes = _panes.size();
481  ii<local_npanes; ++ii, ++it, ++pm_it) {
482  COM::Pane *pane = *it;
483  char *nnf = reinterpret_cast<char*>
484  ( pane->attribute(neighbor_feas->id())->pointer());
485  if ( upgrade_corners) {
486  pnts = reinterpret_cast<Vector_3*>
487  (pane->attribute(COM_NC)->pointer());
488  vss = reinterpret_cast<Vector_3*>
489  (pane->attribute(vecsums_buf->id())->pointer());
490  }
491 
492  std::set< Edge_ID> &eset_pn = _edges[ii];
493  for ( std::set< Edge_ID>::const_iterator eit=eset_pn.begin(),
494  eend = eset_pn.end(); eit!=eend; ++eit) {
495  Edge_ID eid = *eit; COM_assertion(!eid.is_border());
496  Element_node_enumerator ene( pane, eid.eid());
497  int lid = eid.lid(), vindex = ene[lid]-1;
498  ++nnf[vindex];
499 
500  Edge_ID eid_opp = pm_it->get_opposite_real_edge( eid);
501  bool is_border_edge = pm_it->is_physical_border_edge( eid_opp);
502  if ( is_border_edge)
503  ++nnf[ ene[(lid+1)%ene.size_of_edges()]-1];
504 
505  if ( upgrade_corners) {
506  int windex = ene[(lid+1)%ene.size_of_edges()]-1;
507  Vector_3 diff = pnts[ windex] - pnts[vindex];
508  vss[vindex] += diff.normalize();
509 
510  if ( is_border_edge) vss[windex] -= diff;
511  }
512  }
513  }
514  _surf->reduce_on_shared_nodes( neighbor_feas, Manifold::OP_SUM);
515 
516  if ( upgrade_corners)
517  _surf->reduce_on_shared_nodes( vecsums_buf, Manifold::OP_SUM);
518 
519  double tol_sqsin = 4*( 1 - _tol_cos_osta*_tol_cos_osta);
520  int ncrns = 0; // Number of corners
521  // Loop through all vertices to upgrade all the vertices incident on
522  // one or more than two ridge edges.
523  it = _panes.begin();
524  for ( int ii=0, local_npanes = _panes.size(); ii<local_npanes; ++ii, ++it) {
525  COM::Pane *pane = *it;
526  char *nnf = reinterpret_cast<char*>
527  ( pane->attribute(neighbor_feas->id())->pointer());
528  char *tranks = reinterpret_cast<char*>
529  ( pane->attribute(tr_attr->id())->pointer());
530  if ( upgrade_corners)
531  vss = reinterpret_cast<Vector_3*>
532  (pane->attribute(vecsums_buf->id())->pointer());
533 
534  for ( int j=0, nj=pane->size_of_real_nodes(); j<nj; ++j) {
535  if ( upgrade_corners && ( nnf[j]>=3 || nnf[j] == 2 &&
536  vss[j].squared_norm() >= tol_sqsin))
537  tranks[j] = 0; // Upgrade joints to corners
538  else if ( nnf[j] == 0 && std::abs(tranks[j]) == 1)
539  tranks[j] = 2; // Downgrade ridge vertices without neighbors
540  else if ( upgrade_ridge && tranks[j] == 2 && nnf[j] >= 2 ||
541  upgrade_corners && tranks[j] == -1)
542  tranks[j] = 1; // Upgrade ridge vertices with two or more neighbors
543 
544  ncrns += !tranks[j];
545  }
546  }
547 
548  // Reduce tangranks to ensure shared nodes have the same value across panes
549  _surf->reduce_on_shared_nodes( tr_attr, Manifold::OP_MIN);
550 
551  if ( upgrade_corners) {
552  _buf->delete_attribute( vecsums_buf->name());
553  _buf->init_done( false);
554 
555  if ( to_filter)
556  std::cout << "Found " << ncrns << " corner vertices" << std::endl;
557  }
558 }
COM::Window * _buf
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
An adaptor for enumerating node IDs of an element.
double _tol_cos_osta
Definition: FaceOffset_3.h:391
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
Vector_3 & normalize()
Definition: mapbasic.h:114
std::vector< COM::Pane * > _panes
Manifold * _surf
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
j indices j
Definition: Indexing.h:6
std::vector< std::set< Edge_ID > > _edges
Definition: FaceOffset_3.h:427
NT abs(const NT &x)
Definition: number_utils.h:130
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54

Here is the call graph for this function:

Here is the caller graph for this function:

int remove_obscure_curves ( const std::vector< ObscendSet > &  obscends)
protected

Definition at line 780 of file detect_features.C.

References _edges, Propagation_3::_panes, _ridgeneighbors, Propagation_3::_surf, _tangranks, RidgeNeighbor::eid, i, and RidgeNeighbor::vid.

Referenced by filter_obscended_ridge().

780  {
781  // Loop through the panes and ridge edges
782  Manifold::PM_iterator pm_it=_surf->pm_begin();
783 
784  // Remove quasi-obscure edges.
785  int dropped = 0;
786  for ( int i=0, local_npanes = _panes.size();
787  i<local_npanes; ++i, ++pm_it) {
788  std::set< Edge_ID> &eset_pn = _edges[i];
789  const ObscendSet &obscend_pn = obscends[i];
790  COM::Pane *pane = _panes[i];
791 
792  char *tranks = reinterpret_cast<char*>
793  ( pane->attribute(_tangranks->id())->pointer());
794  const RidgeNeighbor *rdgngbs = reinterpret_cast<RidgeNeighbor*>
795  ( pane->attribute(_ridgeneighbors->id())->pointer());
796 
797  std::cout << "There are " << obscend_pn.size()
798  << " obscure curves. " << std::endl;
799 
800  for ( ObscendSet::const_iterator rit=obscend_pn.begin(),
801  rend=obscend_pn.end(); rit!=rend; ++rit) {
802  dropped += eset_pn.erase( rit->first);
803  eset_pn.erase( pm_it->get_opposite_real_edge( rit->first));
804 
805  int cur = rit->second.first, next = rit->second.second, start=cur;
806  for ( ; tranks[next-1]; ) {
807  int index = (next-1)*2;
808  Edge_ID eid;
809 
810  if ( rdgngbs[ index].vid == cur)
811  { cur = next; next = rdgngbs[index+1].vid; eid = rdgngbs[ index+1].eid; }
812  else if ( rdgngbs[ index+1].vid == cur)
813  { cur = next; next = rdgngbs[index].vid; eid = rdgngbs[ index].eid; }
814  else
815  { cur = next; next = 0; }
816  if ( next==0 || next==start) break;
817 
818  dropped += eset_pn.erase( eid);
819  eset_pn.erase( pm_it->get_opposite_real_edge( eid));
820  }
821  }
822  }
823 
824  if ( dropped)
825  std::cerr << "Dropped " << dropped << " false candidate edges. " << std::endl;
826 
827  return dropped;
828 }
COM::Attribute * _ridgeneighbors
Definition: FaceOffset_3.h:422
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
blockLoc i
Definition: read.cpp:79
std::map< Edge_ID, std::pair< int, int > > ObscendSet
Definition: FaceOffset_3.h:40
Manifold * _surf
std::vector< std::set< Edge_ID > > _edges
Definition: FaceOffset_3.h:427

Here is the caller graph for this function:

double rescale_displacements ( COM::Attribute *  disps,
COM::Attribute *  vcenters,
int  depth = 0 
)
protected

Reduce time step based on stability limit, and rescale displacements by the reduced time step and diffusing expansion.

Returns the relative time step.

Definition at line 654 of file FaceOffset_3.C.

References Propagation_3::_buf, _courant, _facenormals, Propagation_3::_panes, Propagation_3::_surf, _tangranks, Rocblas::add(), COM_assertion_msg, COM_NC, COMMPI_Comm_size(), COMMPI_Initialized(), Vector_3< Type >::cross_product(), i, j, k, MPI_LOR, MPI_MIN, Rocblas::mul_scalar(), Element_node_enumerator::next(), nj, Element_node_enumerator::size_of_edges(), and solve_quadratic_func().

Referenced by time_stepping().

655  {
656 
657  double alpha = HUGE_VAL;
658 
659  // Loop through the panes and its real faces
660  std::vector< COM::Pane*>::iterator it = _panes.begin();
661  Manifold::PM_iterator pm_it=_surf->pm_begin();
662  for ( int i=0, local_npanes = _panes.size(); i<local_npanes;
663  ++i, ++it, ++pm_it) {
664  COM::Pane *pane = *it;
665 
666  const Point_3 *pnts = reinterpret_cast<Point_3*>
667  (pane->attribute(COM_NC)->pointer());
668  const Vector_3 *ds = reinterpret_cast<const Vector_3*>
669  ( pane->attribute(disps->id())->pointer());
670  const Vector_3 *vcnts = reinterpret_cast<const Vector_3*>
671  ( pane->attribute(vcenters->id())->pointer());
672  const Vector_3 *fnrms = reinterpret_cast<Vector_3*>
673  ( pane->attribute(_facenormals->id())->pointer());
674  const char *tranks = reinterpret_cast<char*>
675  ( pane->attribute(_tangranks->id())->pointer());
676 
677  // Loop through real elements of the current pane
678  Element_node_enumerator ene( pane, 1);
679 
680  for ( int j=0, nj=pane->size_of_real_elements(); j<nj; ++j, ene.next()) {
681  int ne = ene.size_of_edges();
682  int uindex=ene[ne-1]-1, vindex=ene[0]-1, windex=0;
683 
684  // Loop through all vertices of current face.
685  for ( int k=0; k<ne; ++k, uindex=vindex, vindex=windex ) {
686  windex = ene[(k+1==ne)?0:k+1]-1;
687 
688  if ( k!=0 && ne!=4 && (tranks[uindex] == 2 || tranks[vindex] == 2))
689  continue;
690 
691  Vector_3 tngs[2] = { pnts[uindex]-pnts[vindex],
692  pnts[windex]-pnts[vindex]};
693 
694  Vector_3 disp_v = ds[vindex]+vcnts[vindex];
695  Vector_3 dsps[2] = { ds[uindex]+vcnts[uindex]-disp_v,
696  ds[windex]+vcnts[windex]-disp_v };
697 
698  Vector_3 nrm = Vector_3::cross_product( tngs[0], tngs[1]);
699  Vector_3 dt = Vector_3::cross_product( dsps[0], tngs[1])+
700  Vector_3::cross_product( tngs[0], dsps[1]);
701  Vector_3 dd = Vector_3::cross_product( dsps[0], dsps[1]);
702 
703  double a = dd*nrm;
704  double b = dt*nrm;
705  double c = nrm*nrm;
706 
707  std::pair<double, double> roots=solve_quadratic_func(a,b,c);
708  if ( roots.first<alpha && roots.first>0) alpha = roots.first;
709  if ( roots.second<alpha && roots.second>0) alpha = roots.second;
710 
711  // Solve for time-step constraints at edges.
712  Edge_ID eid(j+1,k), eid_opp = pm_it->get_opposite_real_edge( eid);
713  bool is_border_edge = pm_it->is_physical_border_edge( eid_opp);
714 
715  if ( tranks[uindex] != 2 && tranks[vindex] != 2 && !is_border_edge) {
716  const Vector_3 &n1 = fnrms[j];
717  const Vector_3 &n2 = eid_opp.is_border() ?
718  pm_it->get_bd_normal( eid_opp) : fnrms[eid_opp.eid()-1];
719 
720  nrm = n1+n2;
721  double a = dd*nrm;
722  double b = dt*nrm;
723  double c = nrm*nrm;
724 
725  roots=solve_quadratic_func(a,b,c);
726  if ( roots.first<alpha && roots.first>0) alpha = roots.first;
727  if ( roots.second<alpha && roots.second>0) alpha = roots.second;
728  }
729  }
730  }
731  }
732 
733  // Reduce alpha on all processors.
734  MPI_Comm comm = _buf->get_communicator();
735  int needs_rescale = alpha*_courant<=1;
736 
737  if ( COMMPI_Initialized() && COMMPI_Comm_size( comm)>0) {
738  double local = alpha;
739  MPI_Allreduce(&local, &alpha, 1, MPI_DOUBLE, MPI_MIN, comm);
740 
741  int local_nr = needs_rescale;
742  MPI_Allreduce( &local_nr, &needs_rescale, 1, MPI_INT, MPI_LOR, comm);
743  }
744 
745  // We need to scale back displacement
746  if ( _courant>0 && alpha*_courant<=1) {
747  double scale = 0.9*_courant*alpha;
748 
749  Rocblas::mul_scalar( disps, &scale, disps);
750  Rocblas::mul_scalar( vcenters, &scale, vcenters);
751 
752  const int maxdepth=6;
753  if ( depth>maxdepth) {
754  std::cerr << "Rocprop: Mesh too distorted. Stopping" << std::endl;
755  COM_assertion_msg( depth<=maxdepth, "Too many sub-iterations.");
756  abort();
757  }
758 
759  // Recursively call the function to recompute the scale.
760  return scale*rescale_displacements( disps, vcenters, depth+1);
761  }
762  else {
763  // Add tangential components to normal components.
764  Rocblas::add( disps, vcenters, disps);
765 
766  return 1.;
767  }
768 }
COM::Window * _buf
An adaptor for enumerating node IDs of an element.
j indices k indices k
Definition: Indexing.h:6
#define COM_assertion_msg(EX, msg)
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_MIN
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::pair< double, double > solve_quadratic_func(double a, double b, double c)
Definition: FaceOffset_3.C:772
int COMMPI_Comm_size(MPI_Comm c)
Definition: commpi.h:165
std::vector< COM::Pane * > _panes
static void add(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for addition.
Definition: op3args.C:221
static void mul_scalar(const Attribute *x, const void *y, Attribute *z, int swap=0)
Operation wrapper for multiplication with y as a scalar pointer.
Definition: op3args.C:347
blockLoc i
Definition: read.cpp:79
Manifold * _surf
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_BAND INTEGER MPI_LOR
j indices j
Definition: Indexing.h:6
double rescale_displacements(COM::Attribute *disps, COM::Attribute *vcenters, int depth=0)
Reduce time step based on stability limit, and rescale displacements by the reduced time step and dif...
Definition: FaceOffset_3.C:654
void int * nj
Definition: read.cpp:74
Some basic geometric data types.
Definition: mapbasic.h:54
double _courant
Definition: FaceOffset_3.h:378
int COMMPI_Initialized()
Definition: commpi.h:168
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412

Here is the call graph for this function:

Here is the caller graph for this function:

void reset_default_parameters ( bool  b = false)

Definition at line 44 of file FaceOffset_3.C.

References _conserv, _courant, _dir_thres_strong, _dir_thres_weak, _eig_thres, _eig_weak_lb, _eig_weak_ub, _feature_layer, _inv_sqrt_c, _nrm_dfsn, _smoother, _tol_ad, _tol_angle_strong, _tol_angle_weak, _tol_cos_osta, _tol_eangle, _tol_kangle, _tol_kstrong, _tol_turn_angle, _wf_expn, _wght_scheme, cos, E2N_ANGLE, E2N_AREA, pi, SMOOTHER_LAPLACIAN, sqrt(), Propagation_3::square(), and cimg_library::tan().

Referenced by FaceOffset_3().

44  {
45 
46  // Two default feature modes:
47  if ( feature_preserve) {
48  // Feature-preserving mode: (Recommended for structured meshes)
50  _tol_angle_weak = 18.*pi/180;
51  }
52  else {
53  // Feature-smearing mode: (Recommended for unstructured meshes)
55  _tol_angle_weak = 30.*pi/180.;
56  }
57 
58  _dir_thres_weak = square(tan(0.5*_tol_angle_weak)); // 0.003;
59  _tol_angle_strong = 65.*pi/180;
60  _dir_thres_strong = 0.7;
61 
62  _tol_kstrong = 5;
63  _tol_kangle = (49./180.)*pi;
64  _tol_eangle = (25/180.)*pi;
65 
66  _tol_turn_angle = pi/4.5;
67  _tol_ad = pi/3;
69 
70  _nrm_dfsn = 1; _eig_thres = 0.003;
71  _eig_weak_lb = 1.e-4; _eig_weak_ub = 0.025;
72 
75  _wf_expn = true; _feature_layer=0;
76 }
double _tol_kangle
Definition: FaceOffset_3.h:388
double _eig_weak_ub
Definition: FaceOffset_3.h:397
double _tol_cos_osta
Definition: FaceOffset_3.h:391
double _tol_ad
Definition: FaceOffset_3.h:393
double sqrt(double d)
Definition: double.h:73
CImg< _cimg_Tfloat > tan(const CImg< T > &instance)
Definition: CImg.h:6046
double _inv_sqrt_c
Definition: FaceOffset_3.h:379
double _tol_angle_strong
Definition: FaceOffset_3.h:385
static double square(double x)
double _eig_weak_lb
Definition: FaceOffset_3.h:396
double _tol_eangle
Definition: FaceOffset_3.h:389
double _dir_thres_strong
Definition: FaceOffset_3.h:382
double _tol_angle_weak
Definition: FaceOffset_3.h:384
double _dir_thres_weak
Definition: FaceOffset_3.h:381
static const double pi
Definition: FaceOffset_3.h:429
double _eig_thres
Definition: FaceOffset_3.h:394
double _courant
Definition: FaceOffset_3.h:378
bool _feature_layer
Definition: FaceOffset_3.h:401
double _tol_turn_angle
Definition: FaceOffset_3.h:392
NT & cos

Here is the call graph for this function:

Here is the caller graph for this function:

void set_conserve ( int  b)
inline

Set mass conservation.

Definition at line 125 of file FaceOffset_3.h.

References _conserv.

125 { _conserv = b; }
void set_courant_constant ( double  c)
inline

Set the constant in front of CFL condition (0<=c<1)

Definition at line 83 of file FaceOffset_3.h.

References _courant, _inv_sqrt_c, COM_assertion, and sqrt().

84  { _courant = c; _inv_sqrt_c = 1/std::sqrt(c); COM_assertion(0<=c && c<1); }
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
double sqrt(double d)
Definition: double.h:73
double _inv_sqrt_c
Definition: FaceOffset_3.h:379
double _courant
Definition: FaceOffset_3.h:378

Here is the call graph for this function:

void set_eigen_threshold ( double  eps)
inline

Set the threshold of eigenvalues for splitting primary and null spaces.

Definition at line 76 of file FaceOffset_3.h.

References _eig_thres, and COM_assertion.

77  { _eig_thres = eps; COM_assertion( eps>0 && eps<1); }
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
double _eig_thres
Definition: FaceOffset_3.h:394
void set_fangle_strong ( double  psi)
inline

Set the threshold for weak-feature angle.

Definition at line 100 of file FaceOffset_3.h.

References _tol_angle_strong, and pi.

100  {
101  _tol_angle_strong = psi * pi/180;
102  }
double _tol_angle_strong
Definition: FaceOffset_3.h:385
static const double pi
Definition: FaceOffset_3.h:429
void set_fangle_turn ( double  psi)
inline

Set the threshold for weak-feature angle.

Definition at line 105 of file FaceOffset_3.h.

References _tol_cos_osta, cos, and pi.

105  {
106  _tol_cos_osta = std::cos(psi * pi/360);
107  }
double _tol_cos_osta
Definition: FaceOffset_3.h:391
static const double pi
Definition: FaceOffset_3.h:429
NT & cos
void set_fangle_weak ( double  psi)
inline

Set the threshold for weak-feature angle.

Definition at line 94 of file FaceOffset_3.h.

References _dir_thres_weak, _tol_angle_weak, pi, Propagation_3::square(), and cimg_library::tan().

94  {
95  _tol_angle_weak = psi * pi/180;
97  }
CImg< _cimg_Tfloat > tan(const CImg< T > &instance)
Definition: CImg.h:6046
static double square(double x)
double _tol_angle_weak
Definition: FaceOffset_3.h:384
double _dir_thres_weak
Definition: FaceOffset_3.h:381
static const double pi
Definition: FaceOffset_3.h:429

Here is the call graph for this function:

void set_feature_layer ( bool  b)
inline

Set whether or not to use feature layer.

Definition at line 70 of file FaceOffset_3.h.

References _feature_layer.

70 { _feature_layer = b; }
bool _feature_layer
Definition: FaceOffset_3.h:401
void set_normal_diffusion ( char  i)
inline

Set number of iterations for normal diffusion.

Definition at line 67 of file FaceOffset_3.h.

References _nrm_dfsn, and i.

67 { _nrm_dfsn = i; }
blockLoc i
Definition: read.cpp:79
void set_smoother ( int  smoother)
inline

Set the choice of mesh smoother.

Definition at line 122 of file FaceOffset_3.h.

References _smoother.

122 { _smoother = smoother; }
void set_wavefrontal_expansion ( bool  b)
inline

Set the wavefrontal switch.

Definition at line 61 of file FaceOffset_3.h.

References _wf_expn.

61 { _wf_expn = b; }
void set_weighting_scheme ( int  w)
inline

Weighting scheme.

Definition at line 90 of file FaceOffset_3.h.

References _wght_scheme.

90 { _wght_scheme = w; }
double sign ( double  x)
inlineprotected

Definition at line 312 of file FaceOffset_3.h.

312  {
313  if ( x==0) return 0;
314  if ( x>0) return 1;
315  return -1;
316  }
void int int REAL * x
Definition: read.cpp:74
static void solve ( const FT &  a1,
const FT &  a2,
const FT &  b1,
const FT &  b2,
const FT &  c1,
const FT &  c2,
FT &  x,
FT &  y 
)
inlinestaticprotected

Definition at line 271 of file FaceOffset_3.h.

References denom.

Referenced by solve().

275  {
276  FT denom = a1*b2-b1*a2;
277 
278  x = - (b1*c2-c1*b2)/denom;
279 
280  y = (a1*c2-c1*a2)/denom;
281  }
void int int REAL REAL * y
Definition: read.cpp:74
void int int REAL * x
Definition: read.cpp:74
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom

Here is the caller graph for this function:

static void solve ( const FT &  a1,
const FT &  a2,
const FT &  a3,
const FT &  b1,
const FT &  b2,
const FT &  b3,
const FT &  c1,
const FT &  c2,
const FT &  c3,
const FT &  d1,
const FT &  d2,
const FT &  d3,
FT &  x,
FT &  y,
FT &  z 
)
inlinestaticprotected

Definition at line 284 of file FaceOffset_3.h.

References denom.

289  {
290  FT denom = b2*c1*a3-b1*c2*a3+c3*b1*a2+b3*c2*a1-c1*b3*a2-b2*c3*a1;
291 
292  x = - (b2*c3*d1-b2*c1*d3+c1*b3*d2+b1*c2*d3-c3*b1*d2-b3*c2*d1)/denom;
293 
294  z = (b2*d1*a3-b2*a1*d3+b1*a2*d3-b1*d2*a3-d1*b3*a2+a1*b3*d2)/denom;
295 
296  y = (a2*c3*d1-a2*c1*d3-c2*d1*a3+c2*a1*d3+d2*c1*a3-d2*c3*a1)/denom;
297  }
void int int REAL REAL * y
Definition: read.cpp:74
void int int int REAL REAL REAL * z
Definition: write.cpp:76
void int int REAL * x
Definition: read.cpp:74
CGAL_BEGIN_NAMESPACE void const NT NT NT NT & denom
static void solve ( const Vector_3  A[3],
const Vector_3 q,
Vector_3 x 
)
inlinestaticprotected

Definition at line 300 of file FaceOffset_3.h.

References solve().

302  {
303  solve( A[0][0], A[0][1], A[0][2], A[1][0], A[1][1], A[1][2],
304  A[2][0], A[2][1], A[2][2], q[0], q[1], q[2],
305  x[0], x[1], x[2]);
306  }
static void solve(const FT &a1, const FT &a2, const FT &b1, const FT &b2, const FT &c1, const FT &c2, FT &x, FT &y)
Definition: FaceOffset_3.h:271

Here is the call graph for this function:

std::pair< double, double > solve_quadratic_func ( double  a,
double  b,
double  c 
)
protected

Definition at line 772 of file FaceOffset_3.C.

References NTS::abs(), Mesquite::det(), max(), and sqrt().

Referenced by rescale_displacements().

772  {
773  double max_abc = std::max( std::max(std::abs(a), std::abs(b)), std::abs(c));
774 
775  if ( max_abc > 0)
776  { a /= max_abc; b /= max_abc; c /= max_abc; }
777 
778  if ( a == 0) {
779  if ( b == 0) {
780  return std::make_pair(HUGE_VAL, HUGE_VAL);
781  }
782 
783  return std::make_pair(-c/b, HUGE_VAL);
784  }
785  else {
786  double det = b*b - 4*a*c;
787  if ( det < 0) {
788  return std::make_pair(HUGE_VAL, HUGE_VAL);
789  }
790 
791  double sqrt_d = std::sqrt( det);
792 
793  if ( b>0) {
794  double temp = -b - sqrt_d;
795  return std::make_pair(2*c/temp, 0.5*temp/a);
796  }
797  else {
798  double temp = -b + sqrt_d;
799  return std::make_pair( 0.5*temp/a, 2*c/temp);
800  }
801  }
802 }
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
double sqrt(double d)
Definition: double.h:73
double det(const Matrix3D &A)
NT abs(const NT &x)
Definition: number_utils.h:130

Here is the call graph for this function:

Here is the caller graph for this function:

double time_stepping ( const COM::Attribute *  spds,
double  dt,
COM::Attribute *  disps,
int *  smoothed = NULL 
)
virtual

Main entry of the algorithm.

At input, the value of smoothed specifies whether smoothing is desired.

Implements Propagation_3.

Definition at line 160 of file FaceOffset_3.C.

References Propagation_3::_bnd_set, _boffset, Propagation_3::_buf, Propagation_3::_cnstr_nodes, Propagation_3::_cnstr_set, _courant, _eigvalues, _eigvecs, _faceareas, _facecenters, _facenormals, _is_strtd, Propagation_3::_rank, _ridges, _scales, _smoother, Propagation_3::_surf, _tangranks, _vcenters, Propagation_3::_verb, _vnormals, _weights, _wf_expn, _wght_scheme, Rocblas::add(), Propagation_3::bound_nodal_motion(), COM_assertion_msg, compute_anisotropic_vertex_centers(), compute_directions(), compute_quadrics(), Rocblas::copy(), Rocblas::copy_scalar(), denoise_surface(), E2N_ANGLE, filter_and_identify_ridge_edges(), i, mark_weak_vertices(), Rocblas::mul_scalar(), nulaplacian_smooth(), obtain_constrained_directions(), rescale_displacements(), SMOOTHER_ANISOTROPIC, SMOOTHER_LAPLACIAN, and update_vertex_centers().

161  {
162 
163  COM_assertion_msg( spds || dt==0,
164  "If no speed function, then time step must be zero.");
165 
166  // Inherit speeds and displacement onto the buffer window
167  const COM::Attribute *spds_buf = spds ?
168  ( (spds->window() == _buf) ? spds :
169  _buf->inherit( const_cast<COM::Attribute*>(spds), "speeds_inherited",
170  COM::Pane::INHERIT_USE, true, NULL, 0)) : NULL;
171  COM::Attribute *disps_buf =
172  _buf->inherit( disps, "disps_inherited", COM::Pane::INHERIT_USE,
173  true, NULL, 0);
174  COM::Attribute *disps_tmp =
175  _buf->inherit( disps, "disps_inherited2", COM::Pane::INHERIT_CLONE,
176  true, NULL, 0);
177  _buf->init_done( false);
178 
179  // Compute the face areas and store them.
180  SURF::Rocsurf::compute_element_areas( _faceareas);
181 
182  // First, compute the quadrics to determine the offset intersection
183  // with given time step.
184  bool with_nodal_velo = dt>0 && spds->is_nodal() && spds->size_of_components()==3;
185 
186  // If wavefrontal, then perform two setps.
187  for ( int i=0; i<1+(_wf_expn && dt>0); ++i) {
188  compute_quadrics( dt, spds_buf, _boffset, i ? disps_buf : NULL);
189 
190  if ( with_nodal_velo)
191  Rocblas::mul_scalar( spds, &dt, disps_buf);
192  else
193  Rocblas::copy( _boffset, disps_buf);
194 
195  // Compute mean normals and offset directions during first iteration
196  if ( i==0 && _wf_expn && dt>0) {
197  compute_directions( !with_nodal_velo ? disps_buf : NULL, false);
198 
199  // Enforce constraints.
200  obtain_constrained_directions( disps_buf, NULL);
201  }
202  }
203 
204  // Filter out isolated ridge vertices and identify ridge edges.
207 
208  // Recompute mean normals and offset directions with only primary component
209  compute_directions( (dt!=0 && !with_nodal_velo) ? disps_buf : NULL, true);
210 
211  if ( dt==0)
212  denoise_surface( NULL, disps_buf);
213  else {
214  double zero=0.;
215  Rocblas::copy_scalar( &zero, disps_tmp);
216  denoise_surface( disps_buf, disps_tmp);
217  Rocblas::add( disps_buf, disps_tmp, disps_buf);
218  }
219 
220  bool needs_smoothing=(!smoothed || *smoothed);
221  if ( smoothed) *smoothed = true;
222 
223  if ( !needs_smoothing) {
224  Rocblas::copy( disps_buf, _vcenters);
225  if ( smoothed && *smoothed) *smoothed=false;
226  }
227  else if ( _is_strtd) {
228  update_vertex_centers(); // Update vertex centers for ridge vertices
230  _vcenters, disps_tmp, _weights);
231  }
232  else if ( _smoother == SMOOTHER_ANISOTROPIC) {
233  // Compute anisotropic vertex centers.
235  }
236  update_vertex_centers(); // Update vertex centers for ridge vertices
237 
238  // Recompute face normals if propagation under nodal velocity
239  if ( with_nodal_velo) {
240  _surf->compute_normals( _facenormals);
241  _surf->update_bd_normals( _facenormals, false);
242  }
243 
244  // Constrain the displacements and vertex-centers.
246  if (_bnd_set) {
247  bound_nodal_motion( disps_buf);
248  _surf->reduce_on_shared_nodes( disps_buf, Manifold::OP_MAXABS);
249  }
250 
251 #if EXPORT_DEBUG_INFO
252  COM::Attribute *ctypes = disps->window()->attribute( "cnstr_types_nodal");
253  if ( _cnstr_set && ctypes) Rocblas::copy( _cnstr_nodes, ctypes);
254 
255  COM::Attribute *tranks = disps->window()->attribute( "tangranks");
256  if ( tranks) Rocblas::copy( _tangranks, tranks);
257 
258  COM::Attribute *facenormals = disps->window()->attribute( "facenormals");
259  if ( facenormals) Rocblas::copy( _facenormals, facenormals);
260 
261  COM::Attribute *facecenters = disps->window()->attribute( "facecenters");
262  if ( facecenters) Rocblas::copy( _facecenters, facecenters);
263 
264  COM::Attribute *eigvecs = disps->window()->attribute( "eigvecs");
265  if ( eigvecs) Rocblas::copy( _eigvecs, eigvecs);
266 
267  COM::Attribute *lambdas = disps->window()->attribute( "lambdas");
268  if ( lambdas) Rocblas::copy( _eigvalues, lambdas);
269 
270  COM::Attribute *ridges = disps->window()->attribute( "ridges");
271  if ( ridges)
272  disps->window()->inherit( _ridges, "ridges", COM::Pane::INHERIT_CLONE,
273  true, NULL, 0);
274 
275  if ( dt>0) {
276  COM::Attribute *disps_novis = disps->window()->attribute( "disps_novis");
277  if ( disps_novis) Rocblas::copy( disps, disps_novis);
278  }
279 #endif
280 
281  // Second, reduce time step based on stability limit, and rescale
282  // displacements by the reduced time step and wavefrontal expansion.
283  double dt_sub = dt;
284  if ( _courant>0) {
285  for ( ;;) {
286  double scale = rescale_displacements( disps_buf, _vcenters);
287 
288  if ( scale==1) break;
289 
290  if ( dt==0 && _verb && _rank==0)
291  std::cout << "Rocprop: Scaled back displacement with a factor of "
292  << scale << std::endl;
293 
294  dt_sub *= scale;
295 
296  if ( !with_nodal_velo || _smoother == SMOOTHER_LAPLACIAN) break;
297  // If nodal velocity
298  Rocblas::mul_scalar( spds, &dt_sub, disps_buf);
299  if ( smoothed) smoothed=false;
300  }
301  }
302  else if ( dt==0) {
303  Rocblas::copy( _vcenters, disps_buf);
304  }
305 
306 #if EXPORT_DEBUG_INFO
307  if ( dt>0) {
308  COM::Attribute *scales = disps->window()->attribute( "scales");
309  if ( scales) Rocblas::copy( _scales, scales);
310  }
311 #endif
312 
313  _surf->reduce_on_shared_nodes( disps_buf, Manifold::OP_MAXABS);
314 
315  // Deallocate spds_buf and disps_buf
316  _buf->delete_attribute( disps_tmp->name());
317  _buf->delete_attribute( disps_buf->name());
318  if ( spds_buf && spds_buf!=spds)
319  _buf->delete_attribute( spds_buf->name());
320  _buf->init_done( false);
321 
322  // Finally, return the current time step.
323  return dt_sub;
324 }
COM::Attribute * _scales
Definition: FaceOffset_3.h:424
COM::Attribute * _eigvalues
Definition: FaceOffset_3.h:406
COM::Window * _buf
COM::Attribute * _cnstr_nodes
void filter_and_identify_ridge_edges(bool filter_curves)
Filter out isolated ridge vertices and identify ridge edges.
bool obtain_constrained_directions(COM::Attribute *disps, COM::Attribute *vcenters)
Decompose propagation directions based on constraints.
Definition: FaceOffset_3.C:506
#define COM_assertion_msg(EX, msg)
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
COM::Attribute * _faceareas
Definition: FaceOffset_3.h:414
COM::Attribute * _boffset
Definition: FaceOffset_3.h:404
void update_vertex_centers()
void compute_directions(COM::Attribute *b_offset, bool in_principle)
Compute mean normals.
Definition: FaceOffset_3.C:447
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
void denoise_surface(const COM::Attribute *disps_buf, COM::Attribute *normal_motion)
COM::Attribute * _eigvecs
Definition: FaceOffset_3.h:407
virtual void bound_nodal_motion(COM::Attribute *disps)
COM::Attribute * _facecenters
Definition: FaceOffset_3.h:413
static void add(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for addition.
Definition: op3args.C:221
static void mul_scalar(const Attribute *x, const void *y, Attribute *z, int swap=0)
Operation wrapper for multiplication with y as a scalar pointer.
Definition: op3args.C:347
void compute_quadrics(double dt, const COM::Attribute *spds, COM::Attribute *rhs, COM::Attribute *predicted)
Compute quadrics for every vertex.
blockLoc i
Definition: read.cpp:79
Manifold * _surf
COM::Attribute * _weights
Definition: FaceOffset_3.h:425
void compute_anisotropic_vertex_centers(const COM::Attribute *disps_buf)
COM::Attribute * _ridges
Definition: FaceOffset_3.h:421
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
void mark_weak_vertices()
Mark vertices that are weak.
double rescale_displacements(COM::Attribute *disps, COM::Attribute *vcenters, int depth=0)
Reduce time step based on stability limit, and rescale displacements by the reduced time step and dif...
Definition: FaceOffset_3.C:654
static void copy(const Attribute *x, Attribute *y)
Wrapper for copy.
Definition: op2args.C:333
COM::Attribute * _vnormals
Definition: FaceOffset_3.h:410
double _courant
Definition: FaceOffset_3.h:378
void nulaplacian_smooth(const COM::Attribute *vert_normals, const COM::Attribute *tangranks, const COM::Attribute *disps, COM::Attribute *vcenters, COM::Attribute *buf, COM::Attribute *vert_weights_buf, const COM::Attribute *edge_weights=NULL)
Redistribute smooth vertices by NuLaplacian smoothing.
Definition: NuLaplacian.C:36
COM::Attribute * _facenormals
Definition: FaceOffset_3.h:412

Here is the call graph for this function:

void update_face_volumes ( const COM::Attribute *  fnormal,
const COM::Attribute *  vdsps,
COM::Attribute *  fvol 
)
protected
void update_vertex_centers ( )
protected

Definition at line 267 of file quadric_analysis.C.

References Propagation_3::_buf, Propagation_3::_cnstr_bndry_nodes, _ctangranks, _edges, Propagation_3::_panes, Propagation_3::_surf, _tangranks, _vcenters, COM_DOUBLE, COM_NC, i, j, and Element_node_enumerator::size_of_edges().

Referenced by time_stepping().

267  {
268  COM::Attribute *vcenters_buf =
269  _buf->new_attribute( "FO_vcenters_buf", 'n', COM_DOUBLE, 3, "");
270  COM::Attribute *vecdiff_buf =
271  _buf->new_attribute( "FO_vecdiff_buf", 'n', COM_DOUBLE, 3, "");
272  _buf->resize_array( vcenters_buf, 0);
273  _buf->resize_array( vecdiff_buf, 0);
274 
275  // Loop through the panes and ridge edges
276  std::vector< COM::Pane*>::iterator it = _panes.begin();
277  Manifold::PM_iterator pm_it=_surf->pm_begin();
278 
279  for ( int i=0, local_npanes = _panes.size(); i<local_npanes;
280  ++i, ++it, ++pm_it) {
281  COM::Pane *pane = *it;
282  const std::set< Edge_ID> &eset_pn = _edges[i]; // List of ridge edges
283 
284  const Point_3 *pnts = reinterpret_cast<Point_3*>
285  (pane->attribute(COM_NC)->pointer());
286  Vector_3 *vcs = reinterpret_cast<Vector_3*>
287  (pane->attribute(vcenters_buf->id())->pointer());
288  Vector_3 *vdiff = reinterpret_cast<Vector_3*>
289  (pane->attribute(vecdiff_buf->id())->pointer());
290 
291  for ( std::set< Edge_ID>::const_iterator eit=eset_pn.begin(),
292  eend=eset_pn.end(); eit!=eend; ++eit) {
293  // Make sure that eid_opp is not border
294  Edge_ID eid = *eit, eid_opp = pm_it->get_opposite_real_edge( eid);
295  bool is_border_edge = pm_it->is_physical_border_edge( eid_opp);
296 
297  Element_node_enumerator ene( pane, eid.eid());
298  int lid = eid.lid(), neighbor = (lid+1)%ene.size_of_edges();
299  int vindex = ene[lid]-1, windex = ene[neighbor]-1;
300 
301  // For ridge and flat vertices, compute based on edge centers
302  Vector_3 diff = pnts[ windex] - pnts[vindex];
303  vcs[vindex] += diff;
304  if ( vdiff[vindex].is_null()) vdiff[vindex] = diff;
305  else vdiff[vindex] -= diff;
306 
307  if ( is_border_edge) {
308  vcs[windex] -= diff;
309  if ( vdiff[windex].is_null()) vdiff[windex] = -diff;
310  else vdiff[windex] += diff;
311  }
312  }
313  }
314 
315  _surf->reduce_on_shared_nodes( vcenters_buf, Manifold::OP_SUM);
316  _surf->reduce_on_shared_nodes( vecdiff_buf, Manifold::OP_DIFF);
317 
318  const Vector_3 null_vec(0,0,0);
319  it = _panes.begin();
320  // Finally, copy from vcenters_buf to vcenters
321  for ( int i=0, local_npanes = _panes.size();
322  i<local_npanes; ++i, ++it) {
323  COM::Pane *pane = *it;
324 
325  Vector_3 *vcs_buf = reinterpret_cast<Vector_3*>
326  (pane->attribute(vcenters_buf->id())->pointer());
327  Vector_3 *vcs = reinterpret_cast<Vector_3*>
328  (pane->attribute(_vcenters->id())->pointer());
329  Vector_3 *vdiff = reinterpret_cast<Vector_3*>
330  (pane->attribute(vecdiff_buf->id())->pointer());
331  const char *tranks = reinterpret_cast<const char*>
332  ( pane->attribute(_tangranks->id())->pointer());
333  const char *cranks = reinterpret_cast<const char*>
334  ( pane->attribute(_ctangranks->id())->pointer());
335  const char *val_bndry_nodes = reinterpret_cast<const char*>
336  ( pane->attribute(_cnstr_bndry_nodes->id())->pointer());
337 
338  for (int j=0, jn=pane->size_of_real_nodes(); j<jn; ++j) if (cranks[j]!=2) {
339  if ( cranks[j]==0)
340  vcs[ j] = null_vec;
341  else if ( val_bndry_nodes && val_bndry_nodes[j] && !vdiff[j].is_null()) {
342  vcs_buf[j] = (vcs_buf[j]*vdiff[j]*vdiff[j])/vdiff[j].squared_norm();
343 
344  vcs[ j] = (1./4.)*vcs_buf[j];
345  }
346  }
347  }
348 
349  _buf->delete_attribute( vecdiff_buf->name());
350  _buf->delete_attribute( vcenters_buf->name());
351  _buf->init_done( false);
352 }
COM::Window * _buf
An adaptor for enumerating node IDs of an element.
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
COM::Attribute * _vcenters
Definition: FaceOffset_3.h:415
COM::Attribute * _tangranks
Definition: FaceOffset_3.h:417
std::vector< COM::Pane * > _panes
int size_of_edges() const
Number of edges per element.
blockLoc i
Definition: read.cpp:79
Manifold * _surf
j indices j
Definition: Indexing.h:6
COM::Attribute * _cnstr_bndry_nodes
std::vector< std::set< Edge_ID > > _edges
Definition: FaceOffset_3.h:427
Some basic geometric data types.
Definition: mapbasic.h:54
COM::Attribute * _ctangranks
Definition: FaceOffset_3.h:418

Here is the call graph for this function:

Here is the caller graph for this function:

Member Data Documentation

COM::Attribute* _As
protected
COM::Attribute* _bmedial
protected
COM::Attribute* _boffset
protected

Definition at line 404 of file FaceOffset_3.h.

Referenced by FaceOffset_3(), obtain_constrained_directions(), and time_stepping().

bool _conserv
protected
double _courant
protected
COM::Attribute* _ctangranks
protected
double _dir_thres_strong
protected
double _dir_thres_weak
protected
double _eig_weak_lb
protected

Definition at line 396 of file FaceOffset_3.h.

Referenced by mark_weak_vertices(), and reset_default_parameters().

double _eig_weak_ub
protected

Definition at line 397 of file FaceOffset_3.h.

Referenced by mark_weak_vertices(), and reset_default_parameters().

COM::Attribute* _faceareas
protected
COM::Attribute* _facecenters
protected
COM::Attribute* _facenormals
protected
bool _feature_layer
protected
double _inv_sqrt_c
protected

Definition at line 379 of file FaceOffset_3.h.

Referenced by reset_default_parameters(), and set_courant_constant().

bool _is_strtd
protected

Definition at line 400 of file FaceOffset_3.h.

Referenced by compute_quadrics(), FaceOffset_3(), and time_stepping().

char _nrm_dfsn
protected
COM::Attribute* _ridgeneighbors
protected
COM::Attribute* _ridges
protected

Definition at line 421 of file FaceOffset_3.h.

Referenced by FaceOffset_3(), filter_and_identify_ridge_edges(), and time_stepping().

COM::Attribute* _scales
protected

Definition at line 424 of file FaceOffset_3.h.

Referenced by balance_mass(), FaceOffset_3(), and time_stepping().

char _smoother
protected
double _tol_ad
protected

Definition at line 393 of file FaceOffset_3.h.

Referenced by eigen_analyze_vertex(), and reset_default_parameters().

double _tol_angle_weak
protected
double _tol_eangle
protected

Definition at line 389 of file FaceOffset_3.h.

Referenced by build_ridge_neighbor_list(), and reset_default_parameters().

double _tol_kangle
protected

Definition at line 388 of file FaceOffset_3.h.

Referenced by filter_obscended_ridge(), and reset_default_parameters().

int _tol_kstrong
protected

Definition at line 387 of file FaceOffset_3.h.

Referenced by filter_obscended_ridge(), and reset_default_parameters().

double _tol_turn_angle
protected

Definition at line 392 of file FaceOffset_3.h.

Referenced by build_ridge_neighbor_list(), and reset_default_parameters().

COM::Attribute* _vcenters
protected
COM::Attribute* _vnormals
protected
COM::Attribute* _weak
protected

Definition at line 419 of file FaceOffset_3.h.

Referenced by denoise_surface(), FaceOffset_3(), and mark_weak_vertices().

COM::Attribute* _weights
protected
bool _wf_expn
protected
char _wght_scheme
protected
const double pi = 3.14159265358979
staticprotected

The documentation for this class was generated from the following files: