changeset 54:b7c5d3f5d208

Python class for the creation on the fly of functions. * codeMantainer.py: class which allow us to interact with codeCreator.py * codeCreator.py: class with a template of the function fem_fs, fem_rhs, and fem_lhs. It generates on the fly the executable functions based on the variational problem defined from the user.
author gedeone-octave <marco.vassallo@outlook.com>
date Thu, 25 Jul 2013 11:46:13 +0200
parents 78448b5c6df6
children f04f030ea172
files bin/codeCreator.py bin/codeMantainer.py
diffstat 2 files changed, 467 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/codeCreator.py	Thu Jul 25 11:46:13 2013 +0200
@@ -0,0 +1,392 @@
+'''
+ Copyright (C) 2013 - Juan Pablo Carbajal
+ Copyright (C) 2013 - Marco Vassallo
+
+ This progrm 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/>.
+'''
+
+# Author: Juan Pablo Carbajal <ajuanpi+dev@gmail.com>
+# Modified by: Marco Vassallo
+
+from io import open
+from string import Template
+
+class Makefile ():
+
+  def __init__(self,**kwargs):
+    """ Creates a makefile with the names of the files to be compiled.
+
+    Inuts must be all strings.
+    """
+    if map(type,kwargs.values()) != [str]*len(kwargs):
+      raise ValueError("Makefile accepts only str arguments.")
+
+    self.name = "Makefile_"+kwargs["name"]
+    self.body = Template ("""
+DIR = $path
+CPPFLAGS= -Wall
+LIBS= -ldolfin
+MKOCTFILE = mkoctfile
+FFC = ffc
+
+OCTFILES = fem_fs_$name.oct
+
+all : $(OCTFILES) 
+fs : fem_fs_$name.oct
+rhs : fem_rhs_$name.oct
+lhs : fem_lhs_$name.oct
+
+fem_fs_$name.o: fem_fs_$name.cc
+	$(MKOCTFILE) -I$(DIR) -I. $(CPPFLAGS) $< -c $@
+
+fem_fs_$name.oct: $name.h fem_fs_$name.o
+	$(MKOCTFILE) -s fem_fs_$name.o $(DIR)fem_init_env.o $(LIBS) -o $@
+
+fem_rhs_$name.o: fem_rhs_$name.cc
+	$(MKOCTFILE) -I$(DIR) -I. $(CPPFLAGS) $< -c $@
+
+fem_rhs_$name.oct: $name.h fem_rhs_$name.o
+	$(MKOCTFILE) -s fem_rhs_$name.o $(DIR)fem_init_env.o $(LIBS) -o $@
+
+fem_lhs_$name.o: fem_lhs_$name.cc
+	$(MKOCTFILE) -I$(DIR) -I. $(CPPFLAGS) $< -c $@
+
+fem_lhs_$name.oct: $name.h fem_lhs_$name.o
+	$(MKOCTFILE) -s fem_lhs_$name.o $(DIR)fem_init_env.o $(LIBS) -o $@
+
+$name.h: $name.ufl
+	$(FFC) -l dolfin $name.ufl
+
+.PHONY: clean
+
+clean:
+	 rm -f fem_fs_$name.o fem_fs_$name.cc $name.h
+	 rm -f fem_rhs_$name.o fem_rhs_$name.cc
+	 rm -f fem_lhs_$name.o fem_lhs_$name.cc
+	 rm -f $makefile
+
+""").safe_substitute(name=kwargs["name"],
+                     makefile=self.name,
+                     path=kwargs["path"])
+
+  def writeout (self):
+    mfile = open (self.name, 'w')
+    mfile.write(unicode(self.body))
+    mfile.close()
+
+class Functionspace ():
+
+  def __init__(self,**kwargs):
+    """ Creates a file fem_fs_$name with the name of the Variational problem to.
+
+    Inuts must be all strings.
+    """
+    if map(type,kwargs.values()) != [str]*len(kwargs):
+      raise ValueError("Functionspace accepts only str arguments.")
+
+    self.name = "fem_fs_"+kwargs["name"]+".cc"
+    self.body = Template ("""
+#include "functionspace.h"
+#include "mesh.h"
+#include "$name.h"
+
+DEFUN_DLD (fem_fs_$name, args, , "initialize a fs from a mesh declared with fem_init_mesh")
+{
+  int nargin = args.length ();
+  octave_value retval;
+
+  if (nargin < 1 || nargin > 1)
+    print_usage ();
+  else
+    {
+
+      if (! mesh_type_loaded)
+        {
+          mesh::register_type ();
+          mesh_type_loaded = true;
+          mlock ();
+        }
+
+      if (args(0).type_id () == mesh::static_type_id ())
+        {
+          const mesh & msho = static_cast<const mesh&> (args(0).get_rep ());
+          const dolfin::Mesh & mshd = msho.get_msh ();
+          boost::shared_ptr <const dolfin::FunctionSpace> g (new $name::FunctionSpace (mshd));
+
+          if (! functionspace_type_loaded)
+            {
+              functionspace::register_type ();
+              functionspace_type_loaded = true;
+              mlock ();
+            }
+
+          retval = new functionspace(g);
+        }
+    }
+  return retval;
+}
+""").safe_substitute(name=kwargs["name"])
+
+  def writeout (self):
+    mfile = open (self.name, 'w')
+    mfile.write(unicode(self.body))
+    mfile.close()
+
+class RHS ():
+
+  def __init__(self,**kwargs):
+    """ Creates a file fem_rhs_$name with the name of the Variational problem to.
+
+    Inuts must be all strings.
+    """
+    if map(type,kwargs.values()) != [str]*len(kwargs):
+      raise ValueError("RHS accepts only str arguments.")
+
+    self.name = "fem_rhs_"+kwargs["name"]+".cc"
+    self.body = Template ("""
+#include "$name.h"
+#include "functionspace.h"
+#include "boundarycondition.h"
+#include "coefficient.h"
+
+DEFUN_DLD (fem_rhs_$name, args, , "A = fem_rhs_$name (FUNCTIONAL SPACE, COEFF, BC)")
+{
+
+  int nargin = args.length ();
+  octave_value retval;
+
+  if (nargin < 1)
+    print_usage ();
+  else
+    {
+      if (! functionspace_type_loaded)
+        {
+          functionspace::register_type ();
+          functionspace_type_loaded = true;
+          mlock ();
+        }
+      if (args(0).type_id () == functionspace::static_type_id ())
+        {
+          const functionspace & fspo
+            = static_cast<const functionspace&> (args(0).get_rep ());
+
+          if (! error_state)
+            {
+              const dolfin::FunctionSpace V = fspo.get_fsp ();
+              $name::BilinearForm a (V, V);
+              std::size_t ncoef = a.num_coefficients (), nc = 0;
+
+              if (! coefficient_type_loaded)
+                {
+                  coefficient::register_type ();
+                  coefficient_type_loaded = true;
+                  mlock ();
+                }
+
+              for (std::size_t i = 1; i < nargin; ++i)
+                {
+                  if (args(i).type_id () == coefficient::static_type_id ())
+                    {
+                      const coefficient & cf
+                        = static_cast <const coefficient&> (args(i).get_rep ());
+
+                      std::size_t n = a.coefficient_number (cf.get_str ());
+                      const boost::shared_ptr<const expression> & pexp = cf.get_expr ();
+                      a.set_coefficient (n, pexp);
+                      ++nc;
+                    }
+                 }
+
+              if (nc != ncoef)
+                error ("Wrong number of coefficient");
+              else
+                {
+
+                  dolfin::Matrix A;
+                  dolfin::assemble (A, a);
+
+                  if (! boundarycondition_type_loaded)
+                    {
+                      boundarycondition::register_type ();
+                      boundarycondition_type_loaded = true;
+                      mlock ();
+                    }
+
+                  for (std::size_t i = 1; i < nargin; ++i)
+                    {
+                      if (args(i).type_id () == boundarycondition::static_type_id ())
+                        {
+                          const boundarycondition & bc 
+                            = static_cast<const boundarycondition&> (args(i).get_rep ());
+
+                          const std::vector<boost::shared_ptr <const dolfin::DirichletBC> > & pbc
+                                = bc.get_bc ();
+                              for (std::size_t j = 0; j < pbc.size (); ++j)
+                                pbc[j]->apply(A);
+                        }
+                    }
+
+                  int nr = A.size (0), nc = A.size (1);
+                  // nz shoud be estimated in a better way
+                  int nz = nr * nc;
+                  SparseMatrix sm (nr, nc, nz);
+
+                  int ii = 0;
+                  sm.cidx (0) = 0;
+                  for (int j = 0; j < nc; ++j)
+                   {
+                     for (int i = 0; i < nr; i++)
+                       {
+                         double tmp = A(i, j);
+                         if (tmp != 0.)
+                           {
+                             sm.data(ii) = tmp;
+                             sm.ridx(ii) = i;
+                             ii++;
+                           }
+                       }
+                     sm.cidx(j+1) = ii;
+                  }
+                  sm.maybe_compress ();
+
+                  retval = sm;
+
+                }
+            }
+        }
+    }
+  return retval;
+}
+""").safe_substitute(name=kwargs["name"])
+
+  def writeout (self):
+    mfile = open (self.name, 'w')
+    mfile.write(unicode(self.body))
+    mfile.close()
+
+class LHS ():
+
+  def __init__(self,**kwargs):
+    """ Creates a file fem_lhs_$name with the name of the Variational problem to.
+
+    Inuts must be all strings.
+    """
+    if map(type,kwargs.values()) != [str]*len(kwargs):
+      raise ValueError("lhs accepts only str arguments.")
+
+    self.name = "fem_lhs_"+kwargs["name"]+".cc"
+    self.body = Template ("""
+#include "$name.h"
+#include "functionspace.h"
+#include "boundarycondition.h"
+#include "coefficient.h"
+
+DEFUN_DLD (fem_lhs_$name, args, , " b = fem_lhs_$name (FUNCTIONAL SPACE, COEFF, BC)")
+{
+
+  int nargin = args.length ();
+  octave_value retval;
+
+  if (nargin < 1)
+    print_usage ();
+  else
+    {
+
+      if (! functionspace_type_loaded)
+        {
+          functionspace::register_type ();
+          functionspace_type_loaded = true;
+          mlock ();
+        }
+      if (args(0).type_id () == functionspace::static_type_id ())
+        {
+          const functionspace & fspo
+            = static_cast<const functionspace&> (args(0).get_rep ());
+
+          if (! error_state)
+            {
+              const dolfin::FunctionSpace V = fspo.get_fsp ();
+              $name::LinearForm L (V);
+              std::size_t ncoef = L.num_coefficients (), nc = 0;
+
+              if (! coefficient_type_loaded)
+                {
+                  coefficient::register_type ();
+                  coefficient_type_loaded = true;
+                  mlock ();
+                }
+              for (std::size_t i = 1; i < nargin; ++i)
+                {
+                  if (args(i).type_id () == coefficient::static_type_id ())
+                    {
+                      const coefficient & cf
+                        = static_cast <const coefficient&> (args(i).get_rep ());
+
+                      std::size_t n = L.coefficient_number (cf.get_str ());
+                      const boost::shared_ptr<const expression> & pexp = cf.get_expr ();
+                      L.set_coefficient (n, pexp);
+                      ++nc;
+                    }
+                 }
+
+              if (nc != ncoef)
+                error ("Wrong number of coefficient");
+              else
+                {
+
+                  dolfin::Vector b;
+                  dolfin::assemble (b, L);
+
+                  if (! boundarycondition_type_loaded)
+                    {
+                      boundarycondition::register_type ();
+                      boundarycondition_type_loaded = true;
+                      mlock ();
+                    }
+                  for (std::size_t i = 1; i < nargin; ++i)
+                    {
+                      if (args(i).type_id () == boundarycondition::static_type_id ())
+                        {
+                          const boundarycondition & bc 
+                            = static_cast<const boundarycondition&> (args(i).get_rep ());
+
+                          const std::vector<boost::shared_ptr <const dolfin::DirichletBC> > & pbc
+                                = bc.get_bc ();
+                              for (std::size_t j = 0; j < pbc.size (); ++j)
+                                pbc[j]->apply(b);
+                        }
+                    }
+
+                  dim_vector dims;
+                  dims.resize (2);
+                  dims(0) = b.size ();
+                  dims(1) = 1;
+                  Array<double> myb (dims);
+
+                  for (std::size_t i = 0; i < b.size (); ++i)
+                    myb(i) = b[i];
+
+                  retval = myb;
+                }
+            }
+        }
+    }
+  return retval;
+}
+""").safe_substitute(name=kwargs["name"])
+
+  def writeout (self):
+    mfile = open (self.name, 'w')
+    mfile.write(unicode(self.body))
+    mfile.close()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bin/codeMantainer.py	Thu Jul 25 11:46:13 2013 +0200
@@ -0,0 +1,75 @@
+'''
+ Copyright (C) 2013 - Juan Pablo Carbajal
+ Copyright (C) 2013 - Marco Vassallo
+
+ This progrm 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/>.
+'''
+
+# Author: Juan Pablo Carbajal <ajuanpi+dev@gmail.com>
+# Modified by: Marco Vassallo
+
+from subprocess import check_call
+from subprocess import CalledProcessError
+from os import devnull
+
+import codeCreator as cc
+
+class codeMantainer ():
+
+  def __init__ (self,name, path = "./include/"):
+    self.path= path
+    p = dict (path=self.path)
+
+    self.name = dict (name = name)
+
+    self.mk = [] # placeholder for makefile
+
+    self.make = "make"
+    self.mk_options = [r'--file=Makefile_{name}'.format (**self.name)]
+
+  def runFs (self):
+    with open (devnull, "w") as f:
+      check_call ([self.make] + self.mk_options + ["fs"], stdout=f)
+    return 0
+
+  def runRHS (self):
+    with open (devnull, "w") as f:
+      check_call ([self.make] + self.mk_options + ["rhs"], stdout=f)
+    return 0
+
+  def runLHS (self):
+    with open (devnull, "w") as f:
+      check_call ([self.make] + self.mk_options + ["lhs"], stdout=f)
+    return 0
+
+  def clean (self):
+    with open (devnull, "w") as f:
+      check_call ([self.make] + self.mk_options + ["clean"], stdout=f)
+    return 0
+
+  def updateMakefile(self):
+    self.mk = cc.Makefile(path = self.path, **self.name)
+    self.mk.writeout ()
+
+  def updateFs(self):
+    self.fs = cc.Functionspace (path = self.path, **self.name)
+    self.fs.writeout ()
+
+  def updateRHS(self):
+    self.rhs = cc. RHS (path = self.path, **self.name)
+    self.rhs.writeout ()
+
+  def updateLHS(self):
+    self.lhs = cc. LHS (path = self.path, **self.name)
+    self.lhs.writeout ()