1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
/* *****************************************************************
    MESQUITE -- The Mesh Quality Improvement Toolkit

    Copyright 2010 Sandia National Laboratories.  Developed at the
    University of Wisconsin--Madison under SNL contract number
    624796.  The U.S. Government and the University of Wisconsin
    retain certain rights to this software.

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    (lgpl.txt) along with this library; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

    (2010) [email protected]

  ***************************************************************** */

/** \file DeformingDomainWrapper.hpp
 *  \brief Define DeformingDomainWrapper class
 *  \author Jason Kraftcheck
 */

#ifndef MSQ_DEFORMING_DOMAIN_WRAPPER_HPP
#define MSQ_DEFORMING_DOMAIN_WRAPPER_HPP

#include "Wrapper.hpp"
#include "MeshInterface.hpp"
#include <string>

namespace MBMesquite
{

class CurveDomain;

/**\brief Smooth mesh with deforming domain (deforming geometry)
 *
 * This wrapper stores the initial mesh on/in an undeformed domain
 * and uses the characteristics of that mesh to guide the optimization
 * of the mesh after deformation of the domain.
 *
 * The caller must ensure that the wrapper has the initial mesh
 * description.  The simplest way to do this is to call \c store_initial_mesh
 * prior to the deformation of the geometric domain.
 *
 * Application using this wrapper should preform the following steps.
 * -# Change any wrapper settings
 * -# Call \c store_initial_mesh with a mesh object containing all vertices in the mesh
 * -# If using \c DeformingCurveSmoother, call DeformingCurveSmoother::store_initial_mesh
 *      separately for each geometric curve in the mesh.
 * -# Optionally export mesh to file if \c Mesh implementation can save tag data
 * -# Deform domain
 * -# Optionally restore mesh from file
 * -# Move any vertices bound to geometric points/vertices to their new location
 * -# If using \c DeformingCurveSmoother, call \c smooth_curve separately for each geometric curve
 * -# If doing free smooth call \c run_instructions for entire mesh.  Otherwise
 *       call run_instructions separately for each geometric surface and each
 *       volume.
 *
 *\NOTE This algorithm uses non-barrier metrics which makes it possible, if
 *      unlikely, that the result mesh will contain more/different inverted
 *      elements than the input mesh.
 *
 *\NOTE Mesquite does not do edge/curve smoothing.  The caller may either
 *      set up a "free" smooth where vertices on geometric curves are
 *      smoothed as a part of teh surface or volume optimization or simply
 *      redistribute the vertices along the curves outside of mesquite.
 *      The DeformingCurveSmoother class is provided below to facilitate
 *      redistributing nodes on a curve such that fractional arc length
 *      is preserved for edges.  However, this it is as a stand-alone utility
 *      that must be invoked independently for each curve.
 */
class DeformingDomainWrapper : public Wrapper
{
  public:
    MESQUITE_EXPORT
    DeformingDomainWrapper();

    MESQUITE_EXPORT virtual ~DeformingDomainWrapper();

    /**\brief Specify tag used to get/set cached initial mesh vertex coordinates
     *
     * This optimizer uses the initial mesh (prior to deformation of the
     * domain) as a reference when smoothing the mesh on the deformed domain.
     * The initial mesh is stored/accessed as alternate vertex coordinates
     * stored in a Tag on the mesh.  This function can be used to specify
     * the tag used to store those initial coordinates.  If the named tag
     * already exists then it must have a type of DOUBLE and a size of three values.
     *
     * If the application already has the initial coordinates stored in some
     * tag, then calling this function with the tag handle is sufficient to
     * to set up the optmizer.  Otherwise \c store_initial_mesh can be called
     * to copy the initial vertex coordinates into a tag.  If both this function
     * is called to set the tag handle and \c store_initial_mesh is called, then
     * \c store_initial_mesh will copy the vertices into the specified tag.
     * Otherwise \c store_initial_mesh, if called, will create a new tag.
     */
    inline void set_initial_coord_tag( const std::string& tag_name )
    {
        initVertexCoords = tag_name;
    }

    /**\brief Get tag used to store vertex coordinates of initial mesh
     *
     * Return the tag passed to \c set_initial_coord_tag or if
     * \c store_initial_mesh has been called, the the tag created by
     * \c store_initial_mesh .
     */
    inline std::string get_initial_coord_tag() const
    {
        return initVertexCoords;
    }

    /**\brief Store the initial mesh before deformation as a reference
     *
     * Store the initial mesh for use as a reference when smoothing
     * mesh on deformed geometry.
     *\param mesh The mesh instance to be operated on.  Initial mesh
     *      data is stored by copying vertex coordinates to
     *\Note This must be called prior to the optimization with the
     *      mesh in its undeformed state.
     *\Note This function need not be called if the application cal
     *      provide access to the coordinates of vertices of the initial
     *      mesh through the tag mechanism already.
     *      See \c set_initial_coord_tag
     */
    MESQUITE_EXPORT
    void store_initial_mesh( Mesh* mesh, MsqError& err );

    /**\brief Mesh characteristics to attempt to preserve */
    enum MeshCharacteristic
    {
        SHAPE,             //!< Attempt to preserve element shape (TShapeNB1 metric)
        SHAPE_SIZE,        //!< Attempt to preserve element shape and size (TShapeSize2DNB1 &
                           //!< TShapeSize3DNB1)
        SHAPE_SIZE_ORIENT  //!< Attempt to preserve element shape, size, and orientation
                           //!< (TShapeSizeOrientNB1)
    };

    /**\brief Specify which mesh characteristics to preserve
     *
     * It typically works the best to preserve whichever quantities can
     * be preserved.  For example, if the overall area/volume of the domain
     * didn't change much, attempt to preserve size.  If the deformation of
     * the domain doesn't require rotation of the elements relative to the
     * global coordinate system, then preserve orientation.
     *
     * The default is \c SHAPE.
     */
    inline void set_mesh_characteristic( MeshCharacteristic t )
    {
        metricType = t;
    }

    inline MeshCharacteristic get_mesh_characteristic() const
    {
        return metricType;
    }

    /**\brief Check if vertex culling will be used */
    inline bool is_culling_enabled() const
    {
        return doCulling;
    }

    /**\brief Enable vertex culling.
     *
     * Culling will be enabled by default.
     */
    inline void enable_culling( bool yesno )
    {
        doCulling = yesno;
    }

    /**\brief Specify timeout after which optimization will exit */
    inline void set_cpu_time_limit( double seconds )
    {
        cpuTime = seconds;
    }

    /**\brief No timeout */
    inline void clear_cpu_time_limit()
    {
        cpuTime = 0.0;
    }

    /**\brief Get timeout after which optimization will exit
     *\return false if no timeout specified, true otherwise */
    inline bool get_cpu_time_limit( double& seconds ) const
    {
        seconds = cpuTime;
        return cpuTime > 0.0;
    }

    /**\brief Specify factor by which to minimum distance a vertex must
     *        move in an iteration to avoid termination of the optimization.
     *
     * Value must be greater than zero, and should be less 1.0
     * The optimizer will calculated a representative edge length
     * from the mesh.  It will terminate the optimization when an
     * iteration moves no vertex more than this factor times the
     * characteristic edge length.
     */
    MESQUITE_EXPORT
    void set_vertex_movement_limit_factor( double f );

    inline double get_vertex_movement_limit_factor() const
    {
        return movementFactor;
    }

  protected:
    MESQUITE_EXPORT
    void run_wrapper( MeshDomainAssoc* mesh_and_domain,<--- Function in derived class
                      ParallelMesh* pmesh,
                      Settings* settings,
                      QualityAssessor* qa,
                      MsqError& err );

    MESQUITE_EXPORT
    void move_to_domain( Mesh* mesh, MeshDomain* geom, MsqError& err );

  private:
    MeshCharacteristic metricType;
    std::string initVertexCoords;  //!< name of tag used to store coordinates of initial mesh
    bool doCulling;
    double cpuTime, movementFactor;
};

/**\brief Utility to do curve smoothing
 *
 * This class implements a simple utility to redistribute vertices
 * on a curve (1D domain).  It can operate in two modes.  If the
 * charactristic is \c EQUAL, it will redistribute the vertices such
 * that the arc length between each vertex is equal. In the
 * \c PROPORTIONAL mode the application must call \c store_initial_mesh
 * for each curve before the domain is deformed.  \c store_initial_mesh
 * will record the fractional arc length between vertices so that
 * \c smooth_curve can redistribute the vertices such that the space
 * between the vertices is the same fractional arc length.
 */
class DeformingCurveSmoother
{
  public:
    MESQUITE_EXPORT
    DeformingCurveSmoother();

    MESQUITE_EXPORT
    ~DeformingCurveSmoother();

    /**\brief Mesh characteristics to attempt to preserve */
    enum Scheme
    {
        EQUAL,        //!< space curve vertices equally
        PROPORTIONAL  //!< preserve relative spacing from initial mesh
    };

    /**\brief Specify tag used to get/set cached initial mesh data
     *
     * This optimizer uses the initial mesh (prior to deformation of the
     * domain) as a reference when smoothing the mesh on the deformed domain.
     * This function can be used to store initial mesh data.  If the tag
     * already exists then t must have a type of DOUBLE and a size of one value.
     * the tag used to store those initial coordinates.  It must have a type
     * of DOUBLE and a size of one value.
     */
    inline void set_initial_fraction_tag( const std::string& tag_name )
    {
        initFractTag = tag_name;
    }

    /**\brief Get tag used to store initial mesh characteristics
     *
     * Return the tag handle passed to \c set_initial_fraction_tag or if
     * \c store_initial_mesh, the the tag created by in.
     */
    inline std::string get_initial_fraction_tag() const
    {
        return initFractTag;
    }

    /**\brief Specify which mesh characteristics to preserve */
    inline void set_mesh_characteristic( Scheme t )
    {
        metricType = t;
    }

    inline Scheme get_mesh_characteristic() const
    {
        return metricType;
    }

    /**\brief Record relative edge length from initial mesh
     *
     * Record the necessary characteristics of the initial mesh required
     * for a later all to \c smooth_curve using the \c PROPORTIONAL mode.
     *\param mesh_instance  This mesh instance need not contain only the
     *               vertices of this curve, but it must preserve tag data
     *               on the curve vertices for use in \c smooth_curve.
     *\param vertex_array   The array of handles corresponding to vertices
     *               on the curve and its end points.  Vertices must be
     *               ordered and in the forward direction along the curve,
     *               where the forward direction is whichever direction
     *               the \c CurveDomain instance considers a positive arc
     *               length for the \c position_from_length call.  The array
     *               must also contain both the start and end vertex for
     *               the curve, and if the curve is closed, the single start/end
     *               vertex must occur at both the start and end of the list.
     *\param vertex_array_length The number of handles in \c vertex_array.
     *\param geometry The curve or 1D domain geometry.
     */
    MESQUITE_EXPORT
    void store_initial_mesh( Mesh* mesh_instance,
                             const Mesh::VertexHandle* vertex_array,
                             int vertex_array_length,
                             CurveDomain* geometry,
                             MsqError& err );

    /**\brief Redistribute vertices along a curve or 1D domain.
     *
     * Smooth the curve mesh by redistributing the vertices using one of
     * the schemes defined in \c Scheme.
     *
     *\param mesh_instance  This mesh instance need not contain only the
     *               vertices of this curve, but if using the
     *               \c PROPORTIONAL scheme it must have the tag data
     *               defined by the earlier call to \c store_initial_mesh.
     *\param vertex_array   The array of handles corresponding to vertices
     *               on the curve and its end points.  Vertices must be
     *               ordered and in the forward direction along the curve,
     *               where the forward direction is whichever direction
     *               the \c CurveDomain instance considers a positive arc
     *               length for the \c position_from_length call.  The array
     *               must also contain both the start and end vertex for
     *               the curve, and if the curve is closed, the single start/end
     *               vertex must occur at both the start and end of the list.
     *               The first and last vertex in the array will *not* be moved.
     *               If the geometric points (0D domains) they are constrained
     *               to lie on have moved, the caller must move them to those
     *               new locations before calling this function.
     *\param vertex_array_length The number of handles in \c vertex_array.
     *\param geometry The curve or 1D domain geometry.
     *\param type    The scheme to use.  If using \c PROPORTIONAL,
     *               then \c store_initial_mesh must be called for the same
     *               vertices and mesh instance before any deformation.
     */
    MESQUITE_EXPORT
    void smooth_curve( Mesh* mesh_instance,
                       const Mesh::VertexHandle* vertex_array,
                       int vertex_array_length,
                       CurveDomain* geometry,
                       Scheme type,
                       MsqError& err );

  private:
    Scheme metricType;
    std::string initFractTag;  //!< name of tag used to store arc length fractions
    TagHandle get_tag( Mesh* mesh, MsqError& err );
};

}  // namespace MBMesquite

#endif