line_visualiser.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2023 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 // Header file for line visualiser
27 
28 // Include guard to prevent multiple inclusions of the header
29 #ifndef OOMPH_LINE_VISUALISER_HEADER
30 #define OOMPH_LINE_VISUALISER_HEADER
31 
32 // Config header generated by autoconfig
33 #ifdef HAVE_CONFIG_H
34 #include <oomph-lib-config.h>
35 #endif
36 
37 #include <fstream>
38 #include <iostream>
39 
40 
41 namespace oomph
42 {
43  //====================================================================
44  /// Class to aid visualisation of the values on a set
45  /// of points. NOTE: in a distributed problem, output is only done
46  /// on processor 0.
47  //====================================================================
49  {
50  public:
51  /// Constructor: Pass pointer to mesh and coordinates of
52  /// desired plot points: coord_vec[j][i] is the i-th coordinate of
53  /// the j-th plot point. Optional final parameter specifies the
54  /// maximum search radius in bin when locating the plot points.
55  /// Defaults to DBL_MAX and will therefore keep searching through
56  /// the entire bin structure if a point cannot be found. It's worth
57  /// limiting this to the order of the size of a typical element
58  /// in the mesh in parallel computations with fine meshes, otherwise
59  /// the setup can take forever.
60  LineVisualiser(Mesh* mesh_pt,
61  const Vector<Vector<double>>& coord_vec,
62  const double& max_search_radius = DBL_MAX)
63  : Max_search_radius(max_search_radius),
64  Comm_pt(mesh_pt->communicator_pt())
65  {
66  // Do the actual work
67  setup(mesh_pt, coord_vec);
68  }
69 
70 
71  /// Constructor reading centerline file
72  /// - Open "file_name" and extract 3 first doubles of each line
73  /// - Skip lines which does not begin with a number. Scaling
74  /// factor allows points defined in input file to be scaled.
75  LineVisualiser(Mesh* mesh_pt,
76  const std::string file_name,
77  const double& scale = 1.0)
78  : Max_search_radius(DBL_MAX), Comm_pt(mesh_pt->communicator_pt())
79  {
80  setup_from_file(mesh_pt, file_name, scale);
81  }
82 
83 
84  /// Constructor reading centerline file
85  /// - Open "file_name" and extract 3 first doubles of each line
86  /// - Skip lines which does not begin with a number. Scaling
87  /// factor allows points defined in input file to be scaled.
88  /// Second parameter specifies the
89  /// maximum search radius in bin when locating the plot points. It's worth
90  /// setting this to the order of the size of a typical element
91  /// in the mesh in parallel computations with fine meshes, otherwise
92  /// the setup can take forever.
93  LineVisualiser(Mesh* mesh_pt,
94  const double& max_search_radius,
95  const std::string file_name,
96  const double& scale = 1.0)
97  : Max_search_radius(max_search_radius),
98  Comm_pt(mesh_pt->communicator_pt())
99  {
100  setup_from_file(mesh_pt, file_name, scale);
101  }
102 
103 
104  /// Output function: output each plot point.
105  /// NOTE: in a distributed problem, output is only done
106  /// on processor 0.
107  void output(std::ostream& outfile)
108  {
109  // Get data in array
111  get_output_data(data);
112 
113 
114  // Loop over the points
115  for (unsigned i = 0; i < Nplot_points; i++)
116  {
117  // Get the size of the line
118  unsigned n = data[i].size();
119 
120  // Loop over the values on the line
121  for (unsigned j = 0; j < n; j++)
122  {
123  outfile << data[i][j] << " ";
124  }
125  if (n > 0)
126  {
127  outfile << std::endl;
128  }
129  }
130  }
131 
132  /// Output data function: store data associated with each
133  /// plot point in data array
135  {
136  // Resize output data array
137  data.resize(Nplot_points);
138 
139  // Check if mesh is distributed and a communication pointer
140  // exists.
141  if (Comm_pt != 0)
142  {
143  int nproc = Comm_pt->nproc();
144 
145  if (nproc > 1)
146  {
147 #ifdef OOMPH_HAS_MPI
148 
149  // Declaration of MPI variables
150  MPI_Status stat;
151  int tag = 0;
152  int my_rank = Comm_pt->my_rank();
153 
154 
155  // Buffer
156  unsigned buff_size;
157 
158  // Create array which contains data found in every process
160 
161  // Loop over the points to fill in vec
162  for (unsigned i = 0; i < Nplot_points; i++)
163  {
164  // Check if the point was found in the mesh
165  if (Plot_point[i].first != NULL) // success
166  {
167  // Check if the point is halo
168  if (!((*Plot_point[i].first).is_halo()))
169  {
170  // Get the line of output data from the element
171  // (specified by .first), at its local coordinate
172  // (specified by .second)
173  Plot_point[i].first->point_output_data(Plot_point[i].second,
174  vec[i]);
175  }
176  }
177  }
178 
179 
180  // Analyse which plot points have been found
181  // locally and concatenate the data:
182 
183  // This contains the flat-packed doubles to be sent
184  // for all located plot points
185  Vector<double> local_values;
186 
187  // Number of values to be sent for each plot point
188  // (almost certainly the same for all plot points, but...)
189  // size_values[i] gives the number of doubles to be
190  // sent for plot point i.
191  Vector<unsigned> size_values;
192 
193  // Each processor indicates if it has found a given plot point.
194  // Once this is gathered on the root processor we know
195  // exactly which data we'll receive from where.
196  Vector<unsigned> tmp_proc_point_found_plus_one(Nplot_points, 0);
197 
198  // Loop over the plot points
199  for (unsigned i = 0; i < Nplot_points; i++)
200  {
201  unsigned ndata = vec[i].size();
202  if (ndata != 0)
203  {
204  // Store the number of fields
205  size_values.push_back(ndata);
206 
207  // Update found vector
208  tmp_proc_point_found_plus_one[i] = my_rank + 1;
209 
210  // Store values
211  for (unsigned j = 0; j < ndata; j++)
212  {
213  local_values.push_back(vec[i][j]);
214  }
215  }
216  }
217 
218  // Gather information on root
219 
220  // Find out who's found the points
221  Vector<unsigned> proc_point_found_plus_one(Nplot_points, 0);
222  MPI_Reduce(&tmp_proc_point_found_plus_one[0],
223  &proc_point_found_plus_one[0],
224  Nplot_points,
225  MPI_UNSIGNED,
226  MPI_MAX,
227  0,
228  Comm_pt->mpi_comm());
229 
230 
231  // Main process write data
232  if (my_rank == 0)
233  {
234  // Collect all the data
235  Vector<Vector<double>> received_data(nproc - 1);
236  Vector<Vector<unsigned>> received_size(nproc - 1);
237  Vector<unsigned> counter_d(nproc - 1, 0);
238  Vector<unsigned> counter_s(nproc - 1, 0);
239 
240  // Loop over processors that send their points
241  for (int i = 1; i < nproc; i++)
242  {
243  // Receive sizes of data
244  MPI_Recv(&buff_size,
245  1,
246  MPI_UNSIGNED,
247  i,
248  tag,
249  Comm_pt->mpi_comm(),
250  &stat);
251  received_size[i - 1].resize(std::max(unsigned(1), buff_size));
252  MPI_Recv(&received_size[i - 1][0],
253  buff_size,
254  MPI_UNSIGNED,
255  i,
256  tag,
257  Comm_pt->mpi_comm(),
258  &stat);
259 
260  // Receive actual data
261  MPI_Recv(&buff_size,
262  1,
263  MPI_UNSIGNED,
264  i,
265  tag,
266  Comm_pt->mpi_comm(),
267  &stat);
268  received_data[i - 1].resize(std::max(unsigned(1), buff_size));
269  MPI_Recv(&received_data[i - 1][0],
270  buff_size,
271  MPI_DOUBLE,
272  i,
273  tag,
274  Comm_pt->mpi_comm(),
275  &stat);
276  }
277 
278  // Analyse data for each point
279  for (unsigned i = 0; i < Nplot_points; i++)
280  {
281  // Somebody has found it
282  if (proc_point_found_plus_one[i] != 0)
283  {
284  // Root processor has found it
285  if (proc_point_found_plus_one[i] == 1)
286  {
287  // Copy directly from vec vector
288  data[i] = vec[i];
289  }
290  // Another (non-root) processor has found it
291  else
292  {
293  unsigned line_i = proc_point_found_plus_one[i] - 2;
294 
295  // Resize data line
296  data[i].resize(received_size[line_i][counter_s[line_i]]);
297 
298  // Copy values
299  for (unsigned j = 0;
300  j < received_size[line_i][counter_s[line_i]];
301  j++)
302  {
303  data[i][j] = received_data[line_i][counter_d[line_i] + j];
304  }
305 
306  // Increase counter
307  counter_d[line_i] += received_size[line_i][counter_s[line_i]];
308  counter_s[line_i]++;
309  }
310  } // end somebody has found it -- no output at all if nobody
311  // has found the point (e.g. outside mesh)
312  }
313  }
314  // Send data to root
315  else
316  {
317  // Send the number of fields to the main process
318  buff_size = size_values.size();
319  MPI_Send(&buff_size, 1, MPI_UNSIGNED, 0, tag, Comm_pt->mpi_comm());
320 
321  // Send the sizes of fields to the main process
322  if (buff_size == 0) size_values.resize(1);
323  MPI_Send(&size_values[0],
324  buff_size,
325  MPI_UNSIGNED,
326  0,
327  tag,
328  Comm_pt->mpi_comm());
329 
330  // Send the number of data fields to the main process
331  buff_size = local_values.size();
332  MPI_Send(&buff_size, 1, MPI_UNSIGNED, 0, tag, Comm_pt->mpi_comm());
333 
334  // Send the data to the main process
335  if (buff_size == 0) local_values.resize(1);
336  MPI_Send(&local_values[0],
337  buff_size,
338  MPI_DOUBLE,
339  0,
340  tag,
341  Comm_pt->mpi_comm());
342  }
343 
344 #endif // Serial version
345  }
346  }
347  else
348  {
349  // Loop over the points
350  for (unsigned i = 0; i < Nplot_points; i++)
351  {
352  // Check if the point was found in the mesh
353  if (Plot_point[i].first != NULL) // success
354  {
355  // Copy line into data array
356  Plot_point[i].first->point_output_data(Plot_point[i].second,
357  data[i]);
358  }
359  else // not found -- keep empty block there for debugging
360  {
361  // oomph_info << "Point " << i << " not found\n";
362  }
363  }
364  }
365  }
366 
367 
368  /// Update plot points coordinates (in preparation of remesh,
369  /// say).
371  {
372  // Resize coord_vec
373  coord_vec.resize(Nplot_points);
374 
375  // Check that the communication pointer is initialised and the
376  // problem is distributed.
377  if (Comm_pt != 0)
378  {
379  int nproc = Comm_pt->nproc();
380  if (nproc > 1)
381  {
382 #ifdef OOMPH_HAS_MPI
383 
384  // Declaration of MPI variables
385  MPI_Status stat;
386  int tag; // cgj: tag should be initialised before use
387  int my_rank = Comm_pt->my_rank();
388 
389 
390  // Buffer
391  unsigned buff_size;
392 
393  // Create array which contains data found in every process
395 
396  for (unsigned i = 0; i < Nplot_points; i++)
397  {
398  if (Plot_point[i].first != NULL)
399  {
400  if (!((*Plot_point[i].first).is_halo()))
401  {
402  unsigned dim = Plot_point[i].second.size();
403 
404  vec[i].resize(dim);
405 
406  for (unsigned j = 0; j < dim; j++)
407  {
408  vec[i][j] = Plot_point[i].first->interpolated_x(
409  Plot_point[i].second, j);
410  }
411  }
412  }
413  }
414 
415 
416  // Analyse which plot points have been found
417  // locally and concatenate the data:
418 
419  // This contains the flat-packed doubles to be sent
420  // for all located plot points
421  Vector<double> local_values;
422 
423  // Number of values to be sent for each plot point
424  // (almost certainly the same for all plot points, but...)
425  // size_values[i] gives the number of doubles to be
426  // sent for plot point i.
427  Vector<unsigned> size_values;
428 
429  // Each processor indicates if it has found a given plot point.
430  // Once this is gathered on the root processor we know
431  // exactly which data we'll receive from where.
432  Vector<unsigned> tmp_proc_point_found_plus_one(Nplot_points, 0);
433 
434  // Loop over the plot points
435  for (unsigned i = 0; i < Nplot_points; i++)
436  {
437  unsigned ndata = vec[i].size();
438  if (ndata != 0)
439  {
440  // Store the number of fields
441  size_values.push_back(ndata);
442 
443  // Update found vector
444  tmp_proc_point_found_plus_one[i] = my_rank + 1;
445 
446 
447  // Store values
448  for (unsigned j = 0; j < ndata; j++)
449  {
450  local_values.push_back(vec[i][j]);
451  }
452  }
453  }
454 
455  // Gather information on root
456 
457  // Find out who's found the points
458  Vector<unsigned> proc_point_found_plus_one(Nplot_points, 0);
459  MPI_Reduce(&tmp_proc_point_found_plus_one[0],
460  &proc_point_found_plus_one[0],
461  Nplot_points,
462  MPI_UNSIGNED,
463  MPI_MAX,
464  0,
465  Comm_pt->mpi_comm());
466 
467  // Main process write data
468  if (my_rank == 0)
469  {
470  // Collect all the data
471  Vector<Vector<double>> received_data(nproc - 1);
472  Vector<Vector<unsigned>> received_size(nproc - 1);
473  Vector<unsigned> counter_d(nproc - 1, 0);
474  Vector<unsigned> counter_s(nproc - 1, 0);
475 
476  // Loop over processors that send their points
477  for (int i = 1; i < nproc; i++)
478  {
479  // Receive sizes of data
480  MPI_Recv(&buff_size,
481  1,
482  MPI_UNSIGNED,
483  i,
484  tag,
485  Comm_pt->mpi_comm(),
486  &stat);
487  received_size[i - 1].resize(std::max(unsigned(1), buff_size));
488  MPI_Recv(&received_size[i - 1][0],
489  buff_size,
490  MPI_UNSIGNED,
491  i,
492  tag,
493  Comm_pt->mpi_comm(),
494  &stat);
495 
496  // Receive actual data
497  MPI_Recv(&buff_size,
498  1,
499  MPI_UNSIGNED,
500  i,
501  tag,
502  Comm_pt->mpi_comm(),
503  &stat);
504  received_data[i - 1].resize(std::max(unsigned(1), buff_size));
505  MPI_Recv(&received_data[i - 1][0],
506  buff_size,
507  MPI_DOUBLE,
508  i,
509  tag,
510  Comm_pt->mpi_comm(),
511  &stat);
512  }
513 
514  // Analyse data for each point
515  for (unsigned i = 0; i < Nplot_points; i++)
516  {
517  // Somebody has found it
518  if (proc_point_found_plus_one[i] != 0)
519  {
520  // Root processor has found it
521  if (proc_point_found_plus_one[i] == 1)
522  {
523  // Copy directly from vec vector
524  coord_vec[i] = vec[i];
525  }
526  // Another (non-root) processor has found it
527  else
528  {
529  unsigned line_i = proc_point_found_plus_one[i] - 2;
530 
531  // Resize data line
532  coord_vec[i].resize(received_size[line_i][counter_s[line_i]]);
533 
534  // Copy values
535  for (unsigned j = 0;
536  j < received_size[line_i][counter_s[line_i]];
537  j++)
538  {
539  coord_vec[i][j] =
540  received_data[line_i][counter_d[line_i] + j];
541  }
542 
543  // Increase counter
544  counter_d[line_i] += received_size[line_i][counter_s[line_i]];
545  counter_s[line_i]++;
546  }
547  } // end somebody has found it -- no output at all if nobody
548  // has found the point (e.g. outside mesh)
549  }
550  }
551  // Send data to root
552  else
553  {
554  // Send the number of fields to the main process
555  buff_size = size_values.size();
556  MPI_Send(&buff_size, 1, MPI_UNSIGNED, 0, tag, Comm_pt->mpi_comm());
557 
558  // Send the sizes of fields to the main process
559  if (buff_size == 0) size_values.resize(1);
560  MPI_Send(&size_values[0],
561  buff_size,
562  MPI_UNSIGNED,
563  0,
564  tag,
565  Comm_pt->mpi_comm());
566 
567  // Send the number of data fields to the main process
568  buff_size = local_values.size();
569  MPI_Send(&buff_size, 1, MPI_UNSIGNED, 0, tag, Comm_pt->mpi_comm());
570 
571  // Send the data to the main process
572  if (buff_size == 0) local_values.resize(1);
573  MPI_Send(&local_values[0],
574  buff_size,
575  MPI_DOUBLE,
576  0,
577  tag,
578  Comm_pt->mpi_comm());
579  }
580 
581 #endif // Serial version
582  }
583  }
584  else
585  {
587  }
588  }
589 
590  private:
591  /// Max radius beyond which we stop searching the bin. Initialised
592  /// to DBL_MAX so keep going until the point is found or until
593  /// we've searched every single bin. Overwriting this means we won't search
594  /// in bins whose closest vertex is at a distance greater than
595  /// Max_search_radius from the point to be located.
597 
598  /// Pointer to communicator -- allows us to collect data on
599  /// processor 0 if the mesh is distributed.
601 
602  /// Helper function to setup from file
603  void setup_from_file(Mesh* mesh_pt,
604  const std::string file_name,
605  const double& scale)
606  {
607  // Open file use ifstream
608  std::ifstream file_input(file_name.c_str(), std::ios_base::in);
609  if (!file_input)
610  {
611  std::ostringstream error_message;
612  error_message << "Cannot open file " << file_name << "\n";
613  throw OomphLibError(error_message.str(),
614  OOMPH_CURRENT_FUNCTION,
615  OOMPH_EXCEPTION_LOCATION);
616  }
617  if (!file_input.is_open())
618  {
619  std::ostringstream error_message;
620  error_message << "Cannot open file " << file_name << "\n";
621  throw OomphLibError(error_message.str(),
622  OOMPH_CURRENT_FUNCTION,
623  OOMPH_EXCEPTION_LOCATION);
624  }
625 
626  // Declaration of variables
627  std::string line;
628  Vector<Vector<double>> coord_vec_tmp; // Coord array
629 
630  // Loop over the lines of the input file
631  while (getline(file_input, line) /* != 0*/)
632  {
633  // Test if the first char of the line is a number
634  // using ascii enumeration of chars
635  if (isdigit(line[0]))
636  {
637  Vector<double> tmp(3);
638 
639  // Read the 3 first doubles of the line
640  // Return 3 if success and less if error
641  int n =
642  sscanf(line.c_str(), "%lf %lf %lf", &tmp[0], &tmp[1], &tmp[2]);
643 
644  if (n == 3) // success
645  {
646  // Rescaling
647  for (unsigned i = 0; i < 3; i++)
648  {
649  tmp[i] *= scale;
650  }
651 
652  // Add the new point to the list
653  coord_vec_tmp.push_back(tmp);
654  }
655  else // error
656  {
657  oomph_info << "Line ignored \n";
658  }
659  }
660  }
661 
662  // Call to the helper function
663  setup(mesh_pt, coord_vec_tmp);
664  }
665 
666 
667  /// Helper function to setup the output structures
668  void setup(Mesh* mesh_pt, const Vector<Vector<double>>& coord_vec)
669  {
670  // Read out number of plot points
671  Nplot_points = coord_vec.size();
672 
673  if (Nplot_points == 0) return;
674 
675  // Keep track of unlocated plot points
676  unsigned count_not_found_local = 0;
677 
678  // Dimension
679  unsigned dim = coord_vec[0].size();
680 
681  // Make space
682  Plot_point.resize(Nplot_points);
683 
684  // Transform mesh into a geometric object
685  MeshAsGeomObject mesh_geom_tmp(mesh_pt);
686 
687  // Limit the search radius
688  mesh_geom_tmp.sample_point_container_pt()->max_search_radius() =
690 
691  // Loop over input points
692  double tt_start = TimingHelpers::timer();
693  for (unsigned i = 0; i < Nplot_points; i++)
694  {
695  // Local coordinate of the plot point with its element
696  Vector<double> s(dim, 0.0);
697 
698  // Pointer to GeomObject that contains the plot point
699  GeomObject* geom_pt = 0;
700 
701  // Locate zeta
702  mesh_geom_tmp.locate_zeta(coord_vec[i], geom_pt, s);
703 
704  // Upcast GeomElement as a FiniteElement
705  FiniteElement* fe_pt = dynamic_cast<FiniteElement*>(geom_pt);
706 
707  // Another one not found locally...
708  if (fe_pt == 0)
709  {
710  count_not_found_local++;
711  /* oomph_info << "NOT Found the one at " */
712  /* << coord_vec[i][0] << " " */
713  /* << coord_vec[i][1] << "\n"; */
714  }
715  else
716  {
717  /* oomph_info << "Found the one at " */
718  /* << coord_vec[i][0] << " " */
719  /* << coord_vec[i][1] << "\n"; */
720  }
721 
722  // Save result in a pair
723  Plot_point[i] = std::pair<FiniteElement*, Vector<double>>(fe_pt, s);
724  }
725 
726 
727  oomph_info << "Number of points not found locally: "
728  << count_not_found_local << std::endl;
729 
730  // Global equivalent (is overwritten below if mpi)
731  unsigned count_not_found = count_not_found_local;
732 
733  // Check communication pointer exists and problem is
734  // distributed.
735  if (Comm_pt != 0)
736  {
737  int nproc = Comm_pt->nproc();
738  if (nproc > 1)
739  {
740 #ifdef OOMPH_HAS_MPI
741 
742  // Declaration of MPI variables
743  int my_rank = Comm_pt->my_rank();
744 
745  // Each processor indicates if it has found a given plot point.
746  // Once this is gathered on the root processor we know
747  // exactly which data we'll receive from where.
748  Vector<unsigned> tmp_proc_point_found_plus_one(Nplot_points, 0);
749 
750  // Loop over the plot points
751  for (unsigned i = 0; i < Nplot_points; i++)
752  {
753  // Found locally?
754  if (Plot_point[i].first != 0)
755  {
756  tmp_proc_point_found_plus_one[i] = my_rank + 1;
757  }
758  }
759 
760  // Gather information on root
761 
762  // Find out who's found the points
763  Vector<unsigned> proc_point_found_plus_one(Nplot_points, 0);
764  MPI_Reduce(&tmp_proc_point_found_plus_one[0],
765  &proc_point_found_plus_one[0],
766  Nplot_points,
767  MPI_UNSIGNED,
768  MPI_MAX,
769  0,
770  Comm_pt->mpi_comm());
771 
772 
773  // Main process analyses data
774  if (my_rank == 0)
775  {
776  // Analyse data for each point
777  count_not_found = 0;
778  for (unsigned i = 0; i < Nplot_points; i++)
779  {
780  // Nobody has found it
781  if (proc_point_found_plus_one[i] == 0)
782  {
783  count_not_found++;
784  }
785  }
786  }
787 
788  // Now tell everybody about it
789  MPI_Bcast(&count_not_found, 1, MPI_UNSIGNED, 0, Comm_pt->mpi_comm());
790 
791 #endif
792  }
793  }
794  oomph_info << "Number of plot points not found (with max search radius="
795  << Max_search_radius << ")]: " << count_not_found
796  << "\nTotal time for LineVisualiser setup [sec]: "
797  << TimingHelpers::timer() - tt_start << std::endl;
798  }
799 
800  // Get coordinates of found points
802  {
803  data.resize(Nplot_points);
804  for (unsigned i = 0; i < Nplot_points; i++)
805  {
806  if (Plot_point[i].first != NULL)
807  {
808  unsigned dim = Plot_point[i].second.size();
809 
810  data[i].resize(dim);
811 
812  for (unsigned j = 0; j < dim; j++)
813  {
814  data[i][j] =
815  Plot_point[i].first->interpolated_x(Plot_point[i].second, j);
816  }
817  }
818  }
819  }
820 
821 
822  /// Vector of pairs containing points to finite elements and
823  /// local coordinates
825 
826  /// Number of plot points
827  unsigned Nplot_points;
828 
829  }; // end of class
830 
831 } // namespace oomph
832 
833 #endif
static char t char * s
Definition: cfortran.h:568
cstr elem_len * i
Definition: cfortran.h:603
double & max_search_radius()
Set maximum search radius for locate zeta. This is initialised do DBL_MAX so we brutally search throu...
A general Finite Element class.
Definition: elements.h:1313
/////////////////////////////////////////////////////////////////////
Definition: geom_objects.h:101
Class to aid visualisation of the values on a set of points. NOTE: in a distributed problem,...
OomphCommunicator * Comm_pt
Pointer to communicator – allows us to collect data on processor 0 if the mesh is distributed.
Vector< std::pair< FiniteElement *, Vector< double > > > Plot_point
Vector of pairs containing points to finite elements and local coordinates.
LineVisualiser(Mesh *mesh_pt, const std::string file_name, const double &scale=1.0)
Constructor reading centerline file.
void update_plot_points_coordinates(Vector< Vector< double >> &coord_vec)
Update plot points coordinates (in preparation of remesh, say).
unsigned Nplot_points
Number of plot points.
void setup(Mesh *mesh_pt, const Vector< Vector< double >> &coord_vec)
Helper function to setup the output structures.
void get_output_data(Vector< Vector< double >> &data)
Output data function: store data associated with each plot point in data array.
LineVisualiser(Mesh *mesh_pt, const double &max_search_radius, const std::string file_name, const double &scale=1.0)
Constructor reading centerline file.
double Max_search_radius
Max radius beyond which we stop searching the bin. Initialised to DBL_MAX so keep going until the poi...
LineVisualiser(Mesh *mesh_pt, const Vector< Vector< double >> &coord_vec, const double &max_search_radius=DBL_MAX)
Constructor: Pass pointer to mesh and coordinates of desired plot points: coord_vec[j][i] is the i-th...
void get_local_plot_points_coordinates(Vector< Vector< double >> &data)
void output(std::ostream &outfile)
Output function: output each plot point. NOTE: in a distributed problem, output is only done on proce...
void setup_from_file(Mesh *mesh_pt, const std::string file_name, const double &scale)
Helper function to setup from file.
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
void locate_zeta(const Vector< double > &zeta, GeomObject *&sub_geom_object_pt, Vector< double > &s, const bool &use_coordinate_as_initial_guess=false)
Find the sub geometric object and local coordinate therein that corresponds to the intrinsic coordina...
SamplePointContainer * sample_point_container_pt() const
Pointer to the sample point container.
A general mesh class.
Definition: mesh.h:67
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
Definition: communicator.h:54
An OomphLibError object which should be thrown when an run-time error is encountered....
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition: Vector.h:58
std::string string(const unsigned &i)
Return the i-th string or "" if the relevant string hasn't been defined.
double timer()
returns the time in seconds after some point in past
//////////////////////////////////////////////////////////////////// ////////////////////////////////...
OomphInfo oomph_info
Single (global) instantiation of the OomphInfo object – this is used throughout the library as a "rep...