PRAgMaTIc  master
cpragmatic.cpp
Go to the documentation of this file.
1 /* Copyright (C) 2010 Imperial College London and others.
2  *
3  * Please see the AUTHORS file in the main source directory for a
4  * full list of copyright holders.
5  *
6  * Gerard Gorman
7  * Applied Modelling and Computation Group
8  * Department of Earth Science and Engineering
9  * Imperial College London
10  *
11  * g.gorman@imperial.ac.uk
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  * notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above
19  * copyright notice, this list of conditions and the following
20  * disclaimer in the documentation and/or other materials provided
21  * with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
24  * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
28  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
30  * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
32  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
33  * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
34  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  */
37 
38 #include <cassert>
39 
40 #include "Mesh.h"
41 #include "MetricField.h"
42 #include "Coarsen.h"
43 #include "Refine.h"
44 #include "Swapping.h"
45 #include "Smooth.h"
46 
47 #include "VTKTools.h"
48 
49 static void *_pragmatic_mesh=NULL;
50 static void *_pragmatic_metric_field=NULL;
51 
52 extern "C" {
53  void pragmatic_dump(const char *filename){
55  }
56 
58  pragmatic_dump("dump\0");
59  }
60 
71  void pragmatic_2d_init(const int *NNodes, const int *NElements, const int *enlist, const double *x, const double *y){
72  if(_pragmatic_mesh!=NULL){
73  throw new std::string("PRAgMaTIc: only one mesh can be adapted at a time");
74  }
75 
76  Mesh<double> *mesh = new Mesh<double>(*NNodes, *NElements, enlist, x, y);
77 
79  }
80 
92  void pragmatic_3d_init(const int *NNodes, const int *NElements, const int *enlist, const double *x, const double *y, const double *z){
93  assert(_pragmatic_mesh==NULL);
94  assert(_pragmatic_metric_field==NULL);
95 
96  Mesh<double> *mesh = new Mesh<double>(*NNodes, *NElements, enlist, x, y, z);
97 
99  }
100 
103  void pragmatic_vtk_init(const char *filename){
104  assert(_pragmatic_mesh==NULL);
105  assert(_pragmatic_metric_field==NULL);
106 
108  mesh->create_boundary();
109 
111  }
112 
122  void pragmatic_add_field(const double *psi, const double *error, int *pnorm){
123  assert(_pragmatic_mesh!=NULL);
124 
126 
127  if(_pragmatic_metric_field==NULL){
128  if(((Mesh<double> *)_pragmatic_mesh)->get_number_dimensions()==2){
129  MetricField<double,2> *metric_field = new MetricField<double,2>(*mesh);
130  metric_field->add_field(psi, *error, *pnorm);
131  metric_field->update_mesh();
132 
133  _pragmatic_metric_field = metric_field;
134  }else{
135  MetricField<double,3> *metric_field = new MetricField<double,3>(*mesh);
136  metric_field->add_field(psi, *error, *pnorm);
137  metric_field->update_mesh();
138 
139  _pragmatic_metric_field = metric_field;
140  }
141  }else{
142  std::cerr<<"WARNING: Fortran interface currently only supports adding a single field.\n";
143  }
144  }
145 
150  void pragmatic_set_metric(const double *metric){
151  assert(_pragmatic_mesh!=NULL);
152  assert(_pragmatic_metric_field==NULL);
153 
155 
156  if(_pragmatic_metric_field==NULL){
157  if(((Mesh<double> *)_pragmatic_mesh)->get_number_dimensions()==2){
158  MetricField<double,2> *metric_field = new MetricField<double,2>(*mesh);
159  _pragmatic_metric_field = metric_field;
160  }else{
161  MetricField<double,3> *metric_field = new MetricField<double,3>(*mesh);
162  _pragmatic_metric_field = metric_field;
163  }
164  }
165 
166  if(((Mesh<double> *)_pragmatic_mesh)->get_number_dimensions()==2){
169  }else{
170  ((MetricField<double,3> *)_pragmatic_metric_field)->set_metric_full(metric);
172  }
173  }
174 
181  void pragmatic_set_boundary(const int *nfacets, const int *facets, const int *ids){
182  assert(_pragmatic_mesh!=NULL);
183 
185  mesh->set_boundary(*nfacets, facets, ids);
186  }
187 
192 
193  const size_t ndims = mesh->get_number_dimensions();
194 
195  // See Eqn 7; X Li et al, Comp Methods Appl Mech Engrg 194 (2005) 4915-4950
196  double L_up = sqrt(2.0);
197  double L_low = L_up*0.5;
198 
199  if(ndims==2){
200  Coarsen<double, 2> coarsen(*mesh);
201  Smooth<double, 2> smooth(*mesh);
202  Refine<double, 2> refine(*mesh);
203  Swapping<double, 2> swapping(*mesh);
204 
205  double L_max = mesh->maximal_edge_length();
206 
207  double alpha = sqrt(2.0)/2.0;
208  for(size_t i=0;i<20;i++){
209  double L_ref = std::max(alpha*L_max, L_up);
210 
211  coarsen.coarsen(L_low, L_ref);
212  swapping.swap(0.7);
213  refine.refine(L_ref);
214 
215  L_max = mesh->maximal_edge_length();
216 
217  if(L_max>1.0 && (L_max-L_up)<0.01)
218  break;
219  }
220 
221  mesh->defragment();
222 
223  smooth.smart_laplacian(20);
224  smooth.optimisation_linf(20);
225  }else{
226  Coarsen<double, 3> coarsen(*mesh);
227  Smooth<double, 3> smooth(*mesh);
228  Refine<double, 3> refine(*mesh);
229  Swapping<double, 3> swapping(*mesh);
230 
231  coarsen.coarsen(L_low, L_up);
232 
233  double L_max = mesh->maximal_edge_length();
234 
235  double alpha = sqrt(2.0)/2.0;
236  for(size_t i=0;i<10;i++){
237  double L_ref = std::max(alpha*L_max, L_up);
238 
239  refine.refine(L_ref);
240  coarsen.coarsen(L_low, L_ref);
241  swapping.swap(0.95);
242 
243  L_max = mesh->maximal_edge_length();
244 
245  if((L_max-L_up)<0.01)
246  break;
247  }
248 
249  mesh->defragment();
250 
251  smooth.smart_laplacian(10);
252  smooth.optimisation_linf(10);
253  }
254  }
255 
261  void pragmatic_get_info(int *NNodes, int *NElements){
263 
264  *NNodes = mesh->get_number_nodes();
265  *NElements = mesh->get_number_elements();
266  }
267 
268  void pragmatic_get_coords_2d(double *x, double *y){
269  size_t NNodes = ((Mesh<double> *)_pragmatic_mesh)->get_number_nodes();
270  for(size_t i=0;i<NNodes;i++){
271  x[i] = ((Mesh<double> *)_pragmatic_mesh)->get_coords(i)[0];
272  y[i] = ((Mesh<double> *)_pragmatic_mesh)->get_coords(i)[1];
273  }
274  }
275 
276  void pragmatic_get_coords_3d(double *x, double *y, double *z){
277  size_t NNodes = ((Mesh<double> *)_pragmatic_mesh)->get_number_nodes();
278  for(size_t i=0;i<NNodes;i++){
279  x[i] = ((Mesh<double> *)_pragmatic_mesh)->get_coords(i)[0];
280  y[i] = ((Mesh<double> *)_pragmatic_mesh)->get_coords(i)[1];
281  z[i] = ((Mesh<double> *)_pragmatic_mesh)->get_coords(i)[2];
282  }
283  }
284 
285  void pragmatic_get_elements(int *elements){
286  const size_t ndims = ((Mesh<double> *)_pragmatic_mesh)->get_number_dimensions();
287  const size_t NElements = ((Mesh<double> *)_pragmatic_mesh)->get_number_elements();
288  const size_t nloc = (ndims==2)?3:4;
289 
290  for(size_t i=0;i<NElements;i++){
291  const int *n=((Mesh<double> *)_pragmatic_mesh)->get_element(i);
292 
293  for(size_t j=0;j<nloc;j++){
294  assert(n[j]>=0);
295  elements[i*nloc+j] = n[j];
296  }
297  }
298  }
299 /*
300  void pragmatic_get_lnn2gnn(int *nodes_per_partition, int *lnn2gnn){
301  std::vector<int> _NPNodes, _lnn2gnn;
302  ((Mesh<double> *)_pragmatic_mesh)->get_global_node_numbering(_NPNodes, _lnn2gnn);
303  size_t len0 = _NPNodes.size();
304  for(size_t i=0;i<len0;i++)
305  nodes_per_partition[i] = _NPNodes[i];
306 
307  size_t len1 = _lnn2gnn.size();
308  for(size_t i=0;i<len1;i++)
309  lnn2gnn[i] = _lnn2gnn[i];
310  }
311 */
312  void pragmatic_get_metric(double *metric){
313  if(((Mesh<double> *)_pragmatic_mesh)->get_number_dimensions()==2){
314  ((MetricField<double,2> *)_pragmatic_metric_field)->get_metric(metric);
315  }else{
316  ((MetricField<double,3> *)_pragmatic_metric_field)->get_metric(metric);
317  }
318  }
319 
321  if(((Mesh<double> *)_pragmatic_mesh)->get_number_dimensions()==2){
322  if(_pragmatic_metric_field!=NULL)
324  }else{
325  if(_pragmatic_metric_field!=NULL)
327  }
329 
330  delete (Mesh<double> *)_pragmatic_mesh;
331  _pragmatic_mesh=NULL;
332  }
333 }
void smart_laplacian(int max_iterations=10, double quality_tol=-1.0)
Definition: Smooth.h:111
static Mesh< real_t > * import_vtu(std::string filename)
Definition: VTKTools.h:97
static void * _pragmatic_mesh
Definition: cpragmatic.cpp:49
void update_mesh()
Update the metric field on the mesh.
Definition: MetricField.h:394
void set_metric_full(const real_t *metric)
Definition: MetricField.h:305
void refine(real_t L_max)
Definition: Refine.h:132
void create_boundary()
Definition: Mesh.h:204
Performs 2D mesh coarsening.
Definition: Coarsen.h:59
void pragmatic_3d_init(const int *NNodes, const int *NElements, const int *enlist, const double *x, const double *y, const double *z)
Definition: cpragmatic.cpp:92
Performs edge/face swapping.
Definition: Swapping.h:56
Manages mesh data.
Definition: Mesh.h:70
static void export_vtu(const char *basename, const Mesh< real_t > *mesh, const real_t *psi=NULL)
Definition: VTKTools.h:356
void coarsen(real_t L_low, real_t L_max, bool enable_sliver_deletion=false)
Definition: Coarsen.h:126
Constructs metric tensor field which encodes anisotropic edge size information.
Definition: MetricField.h:73
void add_field(const real_t *psi, const real_t target_error, int p_norm=-1)
Definition: MetricField.h:454
size_t get_number_elements() const
Return the number of elements in the mesh.
Definition: Mesh.h:374
void pragmatic_set_boundary(const int *nfacets, const int *facets, const int *ids)
Definition: cpragmatic.cpp:181
void pragmatic_vtk_init(const char *filename)
Definition: cpragmatic.cpp:103
static void * _pragmatic_metric_field
Definition: cpragmatic.cpp:50
real_t maximal_edge_length() const
Definition: Mesh.h:936
void swap(real_t quality_tolerance)
Definition: Swapping.h:124
void pragmatic_finalize()
Definition: cpragmatic.cpp:320
void pragmatic_get_metric(double *metric)
Definition: cpragmatic.cpp:312
void pragmatic_2d_init(const int *NNodes, const int *NElements, const int *enlist, const double *x, const double *y)
Definition: cpragmatic.cpp:71
void pragmatic_set_metric(const double *metric)
Definition: cpragmatic.cpp:150
size_t get_number_dimensions() const
Return the number of spatial dimensions.
Definition: Mesh.h:379
void pragmatic_add_field(const double *psi, const double *error, int *pnorm)
Definition: cpragmatic.cpp:122
void pragmatic_get_coords_2d(double *x, double *y)
Definition: cpragmatic.cpp:268
size_t get_number_nodes() const
Return the number of nodes in the mesh.
Definition: Mesh.h:369
Applies Laplacian smoothen in metric space.
Definition: Smooth.h:67
void pragmatic_get_info(int *NNodes, int *NElements)
Definition: cpragmatic.cpp:261
void pragmatic_dump(const char *filename)
Definition: cpragmatic.cpp:53
void set_boundary(int nfacets, const int *facets, const int *ids)
Definition: Mesh.h:309
void pragmatic_get_elements(int *elements)
Definition: cpragmatic.cpp:285
void pragmatic_dump_debug()
Definition: cpragmatic.cpp:57
void defragment()
Definition: Mesh.h:958
Performs 2D mesh refinement.
Definition: Refine.h:56
void pragmatic_adapt()
Definition: cpragmatic.cpp:190
void pragmatic_get_coords_3d(double *x, double *y, double *z)
Definition: cpragmatic.cpp:276
void optimisation_linf(int max_iterations=10, double quality_tol=-1.0)
Definition: Smooth.h:240