view bin/codeCreator.py @ 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
children 21eff545a004
line wrap: on
line source

'''
 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()