changeset 255:072aee55bb75

Import UFL in a parallel-safe fashion
author Eugenio Gianniti <eugenio.gianniti@mail.polimi.it>
date Wed, 30 Jul 2014 18:09:13 +0200
parents 2b51546a28f7
children 8fe68d94ab76
files INDEX inst/import_ufl_BilinearForm.m inst/import_ufl_FunctionSpace.m inst/import_ufl_Functional.m inst/import_ufl_LinearForm.m inst/import_ufl_Problem.m inst/ufl.m src/Makefile.in src/barrier.cc src/is_master_node.cc
diffstat 10 files changed, 300 insertions(+), 157 deletions(-) [+]
line wrap: on
line diff
--- a/INDEX	Sat Jul 26 19:38:23 2014 +0200
+++ b/INDEX	Wed Jul 30 18:09:13 2014 +0200
@@ -31,3 +31,6 @@
   @function/plot
   @mesh/plot
   @function/feval
+MPI
+  barrier
+  is_master_node
--- a/inst/import_ufl_BilinearForm.m	Sat Jul 26 19:38:23 2014 +0200
+++ b/inst/import_ufl_BilinearForm.m	Wed Jul 30 18:09:13 2014 +0200
@@ -29,33 +29,38 @@
 
 function import_ufl_BilinearForm (var_prob)
 
-  if nargin != 1
-    error ("import_ufl_BilinearForm: wrong number of input parameters.");
-  elseif ! ischar (var_prob)
-    error ("import_ufl_BilinearForm: first argument is not a valid string");
+  if (is_master_node ())
+    if nargin != 1
+      error ("import_ufl_BilinearForm: wrong number of input parameters.");
+    elseif ! ischar (var_prob)
+      error ("import_ufl_BilinearForm: first argument is not a valid string");
+    endif
+
+    if (check_hash (var_prob) || ! check_oct_files (var_prob, "BilinearForm"))
+      n = length (mfilename ("fullpath")) - length (mfilename());
+      path = strtrunc(mfilename ("fullpath"), n);
+
+      private = fullfile (path, "include/");
+      output = generate_rhs (var_prob);
+      output += generate_makefile (var_prob, private);
+      if output != 0
+        error ("Compilation failed");
+      else
+        [output, textfile] = system (sprintf ("make -f Makefile_%s rhs", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        save_hash (var_prob);
+      endif
+    endif
   endif
 
-  if (check_hash (var_prob) || ! check_oct_files (var_prob, "BilinearForm"))
-    n = length (mfilename ("fullpath")) - length (mfilename());
-    path = strtrunc(mfilename ("fullpath"), n);
+  barrier ();
 
-    private = fullfile (path, "include/");
-    output = generate_rhs (var_prob);
-    output += generate_makefile (var_prob, private);
-    if output != 0
-      error ("Compilation failed");
-    else
-      [output, textfile] = system (sprintf ("make -f Makefile_%s rhs", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      save_hash (var_prob);
-    endif
-  endif
 endfunction
--- a/inst/import_ufl_FunctionSpace.m	Sat Jul 26 19:38:23 2014 +0200
+++ b/inst/import_ufl_FunctionSpace.m	Wed Jul 30 18:09:13 2014 +0200
@@ -27,34 +27,38 @@
 
 function import_ufl_FunctionSpace (var_prob)
 
-  if nargin != 1
-    error ("import_ufl_FunctionSpace: wrong number of input parameters.");
-  elseif ! ischar (var_prob)
-    error ("import_ufl_FunctionSpace: first argument is not a valid string");
-  endif
+  if (is_master_node ())
+    if nargin != 1
+      error ("import_ufl_FunctionSpace: wrong number of input parameters.");
+    elseif ! ischar (var_prob)
+      error ("import_ufl_FunctionSpace: first argument is not a valid string");
+    endif
 
-  if (check_hash (var_prob) || ! check_oct_files (var_prob, "FunctionSpace"))
-    n = length (mfilename ("fullpath")) - length (mfilename());
-    path = strtrunc(mfilename ("fullpath"), n);
+    if (check_hash (var_prob) || ! check_oct_files (var_prob, "FunctionSpace"))
+      n = length (mfilename ("fullpath")) - length (mfilename());
+      path = strtrunc(mfilename ("fullpath"), n);
 
-    private = fullfile (path, "include/");
-    output = generate_fs (var_prob);
-    output += generate_makefile (var_prob, private);
-    if output != 0
-      error ("Compilation failed");
-    else
-      [output, textfile] = system (sprintf ("make -f Makefile_%s fs", var_prob));
+      private = fullfile (path, "include/");
+      output = generate_fs (var_prob);
+      output += generate_makefile (var_prob, private);
       if output != 0
-        display (text);
         error ("Compilation failed");
+      else
+        [output, textfile] = system (sprintf ("make -f Makefile_%s fs", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        save_hash (var_prob);
       endif
-      [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      save_hash (var_prob);
     endif
   endif
 
+  barrier ();
+
 endfunction
--- a/inst/import_ufl_Functional.m	Sat Jul 26 19:38:23 2014 +0200
+++ b/inst/import_ufl_Functional.m	Wed Jul 30 18:09:13 2014 +0200
@@ -26,33 +26,38 @@
 ## @end deftypefn
 function import_ufl_Functional (var_prob)
 
-  if nargin != 1
-    error ("import_ufl_Functional: wrong number of input parameters.");
-  elseif ! ischar (var_prob)
-    error ("import_ufl_Functional: first argument is not a valid string");
+  if (is_master_node ())
+    if nargin != 1
+      error ("import_ufl_Functional: wrong number of input parameters.");
+    elseif ! ischar (var_prob)
+      error ("import_ufl_Functional: first argument is not a valid string");
+    endif
+
+    if (check_hash (var_prob) || ! check_oct_files (var_prob, "Functional"))
+      n = length (mfilename ("fullpath")) - length (mfilename());
+      path = strtrunc(mfilename ("fullpath"), n);
+
+      private = fullfile (path, "include/");
+      output = generate_fun (var_prob);
+      output += generate_makefile (var_prob, private);
+      if output != 0
+        error ("Compilation failed");
+      else
+        [output, textfile] = system (sprintf ("make -f Makefile_%s fun", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        save_hash (var_prob);
+      endif
+    endif
   endif
 
-  if (check_hash (var_prob) || ! check_oct_files (var_prob, "Functional"))
-    n = length (mfilename ("fullpath")) - length (mfilename());
-    path = strtrunc(mfilename ("fullpath"), n);
+  barrier ();
 
-    private = fullfile (path, "include/");
-    output = generate_fun (var_prob);
-    output += generate_makefile (var_prob, private);
-    if output != 0
-      error ("Compilation failed");
-    else
-      [output, textfile] = system (sprintf ("make -f Makefile_%s fun", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      save_hash (var_prob);
-    endif
-  endif
 endfunction
--- a/inst/import_ufl_LinearForm.m	Sat Jul 26 19:38:23 2014 +0200
+++ b/inst/import_ufl_LinearForm.m	Wed Jul 30 18:09:13 2014 +0200
@@ -27,34 +27,39 @@
 
 function import_ufl_LinearForm (var_prob)
 
-  if nargin != 1
-    error ("import_ufl_LinearForm: wrong number of input parameters.");
-  elseif ! ischar (var_prob)
-    error ("import_ufl_LinearForm: first argument is not a valid string");
+  if (is_master_node ())
+    if nargin != 1
+      error ("import_ufl_LinearForm: wrong number of input parameters.");
+    elseif ! ischar (var_prob)
+      error ("import_ufl_LinearForm: first argument is not a valid string");
+    endif
+
+    if (check_hash (var_prob) || ! check_oct_files (var_prob, "LinearForm"))
+      n = length (mfilename ("fullpath")) - length (mfilename());
+      path = strtrunc(mfilename ("fullpath"), n);
+
+      private = fullfile (path, "include/");
+
+      output = generate_lhs (var_prob);
+      output += generate_makefile (var_prob, private);
+      if output != 0
+        error ("Compilation failed");
+      else
+        [output, textfile] = system (sprintf ("make -f Makefile_%s lhs", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        save_hash (var_prob);
+      endif
+    endif
   endif
 
-  if (check_hash (var_prob) || ! check_oct_files (var_prob, "LinearForm"))
-    n = length (mfilename ("fullpath")) - length (mfilename());
-    path = strtrunc(mfilename ("fullpath"), n);
-
-    private = fullfile (path, "include/");
+  barrier ();
 
-    output = generate_lhs (var_prob);
-    output += generate_makefile (var_prob, private);
-    if output != 0
-      error ("Compilation failed");
-    else
-      [output, textfile] = system (sprintf ("make -f Makefile_%s lhs", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      save_hash (var_prob);
-    endif
-  endif
 endfunction
--- a/inst/import_ufl_Problem.m	Sat Jul 26 19:38:23 2014 +0200
+++ b/inst/import_ufl_Problem.m	Wed Jul 30 18:09:13 2014 +0200
@@ -26,36 +26,40 @@
 
 function import_ufl_Problem (var_prob)
 
-  if nargin != 1
-    error ("import_ufl_Problem: wrong number of input parameters.");
-  elseif ! ischar (var_prob)
-    error ("import_ufl_Problem: first argument is not a valid string");
-  endif
+  if (is_master_node ())
+    if nargin != 1
+      error ("import_ufl_Problem: wrong number of input parameters.");
+    elseif ! ischar (var_prob)
+      error ("import_ufl_Problem: first argument is not a valid string");
+    endif
 
-  if (check_hash (var_prob) || ! check_oct_files (var_prob, "Problem"))
-    n = length (mfilename ("fullpath")) - length (mfilename());
-    path = strtrunc(mfilename ("fullpath"), n);
+    if (check_hash (var_prob) || ! check_oct_files (var_prob, "Problem"))
+      n = length (mfilename ("fullpath")) - length (mfilename());
+      path = strtrunc(mfilename ("fullpath"), n);
 
-    private = fullfile (path, "include/");
-    output = generate_fs (var_prob);
-    output += generate_rhs (var_prob);
-    output += generate_lhs (var_prob);
-    output += generate_makefile (var_prob, private);
-    if output != 0
-      error ("Compilation failed");
-    else
-      [output, textfile] = system (sprintf ("make -f Makefile_%s all", var_prob));
+      private = fullfile (path, "include/");
+      output = generate_fs (var_prob);
+      output += generate_rhs (var_prob);
+      output += generate_lhs (var_prob);
+      output += generate_makefile (var_prob, private);
       if output != 0
-        display (text);
         error ("Compilation failed");
+      else
+        [output, textfile] = system (sprintf ("make -f Makefile_%s all", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
+        if output != 0
+          display (text);
+          error ("Compilation failed");
+        endif
+        save_hash (var_prob);
       endif
-      [output, textfile] = system (sprintf ("make -f Makefile_%s clean", var_prob));
-      if output != 0
-        display (text);
-        error ("Compilation failed");
-      endif
-      save_hash (var_prob);
     endif
   endif
 
+  barrier ();
+
 endfunction
--- a/inst/ufl.m	Sat Jul 26 19:38:23 2014 +0200
+++ b/inst/ufl.m	Wed Jul 30 18:09:13 2014 +0200
@@ -59,56 +59,70 @@
                      "Problem"};
 
   if (numel (varargin) < 1)
-    if (! is_valid_file_id (fid))
+    if (is_master_node () && ! is_valid_file_id (fid))
       print_usage ();
     endif
   elseif (! all (cellfun ("ischar", varargin)))
-    error ("ufl: all arguments should be strings");
+    if (is_master_node ())
+      error ("ufl: all arguments should be strings");
+    endif
   elseif (strcmpi (varargin{1}, "start"))
-    if (is_valid_file_id (fid))
-      error ("ufl: a file is already open");
-    else
-      if (numel (varargin) > 1)
-        filename = varargin{2};
-        if (isempty (regexpi (filename, ".ufl$", "match")))
-          filename = [filename, ".ufl"];
+    if (is_master_node ())
+      if (is_valid_file_id (fid))
+        error ("ufl: a file is already open");
+      else
+        if (numel (varargin) > 1)
+          filename = varargin{2};
+          if (isempty (regexpi (filename, ".ufl$", "match")))
+            filename = [filename, ".ufl"];
+          else
+            filename = [filename(1:end-4), ".ufl"];
+          endif
+        endif
+        [~, err, ~] = stat (filename);
+        if (err == 0)
+          error (["ufl: a file named ", filename, " already exists"]);
         else
-          filename = [filename(1:end-4), ".ufl"];
+          fid = fopen (filename, "w");
         endif
       endif
-      [~, err, ~] = stat (filename);
-      if (err == 0)
-        error (["ufl: a file named ", filename, " already exists"]);
-      else
-        fid = fopen (filename, "w");
+      if (! is_valid_file_id (fid))
+        error (["ufl: could not open file ", filename]);
       endif
     endif
-    if (! is_valid_file_id (fid))
-      error (["ufl: could not open file ", filename]);
-    endif
   elseif (strcmpi (varargin{1}, "end"))
-    if (! is_valid_file_id (fid))
-      error ("ufl: no open file");
-    else
-      fclose (fid);
-      fid = -1;
+    if (is_master_node ())
+      if (! is_valid_file_id (fid))
+        error ("ufl: no open file");
+      else
+        fclose (fid);
+        fid = -1;
+      endif
     endif
     compile = "Problem";
     if (numel (varargin) > 1)
       compile = validatestring (varargin{2}, opts, "ufl", "content");
     endif
+    # This line is executed by all the nodes since it internally enforces
+    # that just one is involved
     eval (["import_ufl_", compile, "(\"", filename(1:end-4), "\");"]);
-    delete (filename);
+    if (is_master_node ())
+      delete (filename);
+    endif
     filename = "default.ufl";
   elseif (! is_valid_file_id (fid))
-    error ("ufl: no open file");
+    if (is_master_node ())
+      error ("ufl: no open file");
+    endif
   else
-    if (is_valid_file_id (fid))
-      output = strtrim (sprintf ("%s ", varargin{:}));
-      fputs (fid, output);
-      fprintf (fid, "\n");
-    else
-      error ("ufl: no open file");
+    if (is_master_node ())
+      if (is_valid_file_id (fid))
+        output = strtrim (sprintf ("%s ", varargin{:}));
+        fputs (fid, output);
+        fprintf (fid, "\n");
+      else
+        error ("ufl: no open file");
+      endif
     endif
   endif
 
--- a/src/Makefile.in	Sat Jul 26 19:38:23 2014 +0200
+++ b/src/Makefile.in	Wed Jul 30 18:09:13 2014 +0200
@@ -39,7 +39,9 @@
              plot_mesh.oct \
              SubSpace.oct \
              feval.oct \
-             interpolate.oct
+             interpolate.oct \
+             is_master_node.oct \
+             barrier.oct
 
 
 all: $(OCTFILES)
@@ -152,6 +154,18 @@
 libfemfenics_factories.a: femfenics_factory.o uBLAS_factory.o PETSc_factory.o
 	$(AR) $(ARFLAGS) $@ $^
 
+is_master_node.oct: is_master_node.o
+	CPPFLAGS=$(CPPFLAGS) $(MKOCTFILE) -o $@ $< $(LIBS)
+
+is_master_node.o: is_master_node.cc dolfin_compat.h
+	CPPFLAGS=$(CPPFLAGS) $(MKOCTFILE) -o $@ -c $<
+
+barrier.oct: barrier.o
+	CPPFLAGS=$(CPPFLAGS) $(MKOCTFILE) -o $@ $< $(LIBS)
+
+barrier.o: barrier.cc dolfin_compat.h
+	CPPFLAGS=$(CPPFLAGS) $(MKOCTFILE) -o $@ -c $<
+
 clean:
 	$(RM) *.o core octave-core *.oct *~ *.xml *.a
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/barrier.cc	Wed Jul 30 18:09:13 2014 +0200
@@ -0,0 +1,44 @@
+/*
+ Copyright (C) 2014 Eugenio Gianniti <eugenio.gianniti@mail.polimi.it>
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3 of the License, or (at your option) any later
+ version.
+
+ This program 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 General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <dolfin.h>
+#include <octave/oct.h>
+#include "dolfin_compat.h"
+
+DEFUN_DLD (barrier, args, nargout,
+"-*- texinfo -*-\n\
+@deftypefn {Function File} {} \
+barrier ()\n\
+Set an MPI barrier.\n\
+@end deftypefn")
+{
+  octave_value retval;
+  int nargin = args.length ();
+
+  if (nargin > 0 || nargout > 0)
+    print_usage ();
+  else
+    {
+      dolfin::MPI::barrier (
+#ifdef LATEST_DOLFIN
+                            MPI_COMM_WORLD
+#endif
+                           );
+    }
+
+  return retval;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/is_master_node.cc	Wed Jul 30 18:09:13 2014 +0200
@@ -0,0 +1,45 @@
+/*
+ Copyright (C) 2014 Eugenio Gianniti <eugenio.gianniti@mail.polimi.it>
+
+ This program is free software; you can redistribute it and/or modify it under
+ the terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3 of the License, or (at your option) any later
+ version.
+
+ This program 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 General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <dolfin.h>
+#include <octave/oct.h>
+#include "dolfin_compat.h"
+
+DEFUN_DLD (is_master_node, args, nargout,
+"-*- texinfo -*-\n\
+@deftypefn {Function File} {} \
+is_master_process ()\n\
+Return true if called on node zero.\n\
+@end deftypefn")
+{
+  octave_value retval;
+  int nargin = args.length ();
+
+  if (nargin > 0 || nargout > 1)
+    print_usage ();
+  else
+    {
+#ifdef LATEST_DOLFIN
+      retval = (dolfin::MPI::rank (MPI_COMM_WORLD) == 0);
+#else
+      // This works also in 1.4.0, but it is now deprecated
+      retval = (dolfin::MPI::process_number () == 0);
+#endif
+    }
+
+  return retval;
+}