fenics team mailing list archive
-
fenics team
-
Mailing list archive
-
Message #00894
Re: [Branch ~fenics-core/fenics-doc/main] Rev 14: Added script to check code blocks in the demo directories and fixed some inconsistencies that the...
-
To:
FEniCS Mailing List <fenics@xxxxxxxxxxxxxxxxxxx>
-
From:
Anders Logg <logg@xxxxxxxxx>
-
Date:
Sat, 1 May 2010 19:27:04 +0200
-
In-reply-to:
<20100501152719.26358.32990.launchpad@loganberry.canonical.com>
-
User-agent:
Mutt/1.5.20 (2009-06-14)
Cool!
--
Anders
On Sat, May 01, 2010 at 03:27:19PM -0000, noreply@xxxxxxxxxxxxx wrote:
> ------------------------------------------------------------
> revno: 14
> committer: Kristian B. Ølgaard <k.b.oelgaard@xxxxxxxxx>
> branch nick: fenics-doc
> timestamp: Sat 2010-05-01 17:25:57 +0200
> message:
> Added script to check code blocks in the demo directories and fixed some inconsistencies that the script found.
> added:
> source/demos/python/pde/poisson/demo.py
> verify_code_snippets.py
> modified:
> source/demos/cpp/pde/cahn-hilliard/cahn-hilliard.rst
> source/demos/cpp/pde/poisson/poisson.rst
> source/demos/python/pde/cahn-hilliard/cahn-hilliard.rst
> source/demos/python/pde/poisson/poisson.rst
>
>
> === modified file 'source/demos/cpp/pde/cahn-hilliard/cahn-hilliard.rst'
> --- source/demos/cpp/pde/cahn-hilliard/cahn-hilliard.rst 2010-04-29 11:35:24 +0000
> +++ source/demos/cpp/pde/cahn-hilliard/cahn-hilliard.rst 2010-05-01 15:25:57 +0000
> @@ -56,47 +56,51 @@
>
> .. code-block:: c++
>
> - #include <dolfin.h>
> - #include "Poisson.h"
> + #include <dolfin.h>
> + #include "CahnHilliard2D.h"
> + #include "CahnHilliard3D.h"
>
> - using namespace dolfin;
> + using namespace dolfin;
>
> Some more C++
>
> .. code-block:: c++
>
> - // Source term (right-hand side)
> - class Source : public Expression
> - {
> - void eval(Array<double>& values, const Array<double>& x) const
> - {
> - double dx = x[0] - 0.5;
> - double dy = x[1] - 0.5;
> - values[0] = 10*exp(-(dx*dx + dy*dy) / 0.02);
> - }
> - };
> -
> - // Boundary flux (Neumann boundary condition)
> - class Flux : public Expression
> - {
> - void eval(Array<double>& values, const Array<double>& x) const
> - {
> - values[0] = -sin(5*x[0]);
> - }
> - };
> + // Initial conditions
> + class InitialConditions : public Expression
> + {
> + public:
> +
> + InitialConditions(const Mesh& mesh) : Expression(mesh.topology().dim())
> + {
> + dolfin::seed(2);
> + }
> +
> + void eval(Array<double>& values, const Data& data) const
> + {
> + values[0]= 0.0;
> + values[1]= 0.63 + 0.02*(0.5 - dolfin::rand());
> + }
> +
> + };
>
> Yet more C++
>
> .. code-block:: c++
>
> - // Sub domain for Dirichlet boundary condition
> - class DirichletBoundary : public SubDomain
> + // Solve
> + while (t < T)
> {
> - bool inside(const Array<double>& x, bool on_boundary) const
> - {
> - return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS;
> - }
> - };
> + // Update for next time step
> + t += dt;
> + u0.vector() = u.vector();
> +
> + // Solve
> + newton_solver.solve(cahn_hilliard, u.vector());
> +
> + // Save function to file
> + file << u[1];
> + }
>
> All this should be in the same :download:`main.cpp` file.
>
>
> === modified file 'source/demos/cpp/pde/poisson/poisson.rst'
> --- source/demos/cpp/pde/poisson/poisson.rst 2010-04-29 11:35:24 +0000
> +++ source/demos/cpp/pde/poisson/poisson.rst 2010-05-01 15:25:57 +0000
> @@ -24,7 +24,7 @@
> g = Coefficient(element)
>
> a = inner(grad(v), grad(u))*dx
> - L = v*f*dx + v*h*ds
> + L = v*f*dx + v*g*ds
>
>
> Some C++
>
> === modified file 'source/demos/python/pde/cahn-hilliard/cahn-hilliard.rst'
> --- source/demos/python/pde/cahn-hilliard/cahn-hilliard.rst 2010-04-29 11:35:24 +0000
> +++ source/demos/python/pde/cahn-hilliard/cahn-hilliard.rst 2010-05-01 15:25:57 +0000
> @@ -10,3 +10,6 @@
> .. include:: ../../../common/pde/cahn-hilliard/cahn-hilliard.txt
>
> This text is Python specific
> +
> +
> +
>
> === added file 'source/demos/python/pde/poisson/demo.py'
> --- source/demos/python/pde/poisson/demo.py 1970-01-01 00:00:00 +0000
> +++ source/demos/python/pde/poisson/demo.py 2010-05-01 15:25:57 +0000
> @@ -0,0 +1,51 @@
> +"""This demo program solves Poisson's equation
> +
> + - div grad u(x, y) = f(x, y)
> +
> +on the unit square with source f given by
> +
> + f(x, y) = 10*exp(-((x - 0.5)^2 + (y - 0.5)^2) / 0.02)
> +
> +and boundary conditions given by
> +
> + u(x, y) = 0 for x = 0 or x = 1
> +du/dn(x, y) = -sin(5*x) for y = 0 or y = 1
> +"""
> +
> +__author__ = "Anders Logg (logg@xxxxxxxxx)"
> +__date__ = "2007-08-16 -- 2010-03-05"
> +__copyright__ = "Copyright (C) 2007-2009 Anders Logg"
> +__license__ = "GNU LGPL Version 2.1"
> +
> +from dolfin import *
> +
> +# Create mesh and define function space
> +mesh = UnitSquare(32, 32)
> +V = FunctionSpace(mesh, "CG", 1)
> +
> +# Define Dirichlet boundary (x = 0 or x = 1)
> +def boundary(x):
> + return x[0] < DOLFIN_EPS or x[0] > 1.0 - DOLFIN_EPS
> +
> +# Define boundary condition
> +u0 = Constant(0.0)
> +bc = DirichletBC(V, u0, boundary)
> +
> +# Define variational problem
> +v = TestFunction(V)
> +u = TrialFunction(V)
> +f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)")
> +g = Expression("-sin(5*x[0])")
> +a = inner(grad(v), grad(u))*dx
> +L = v*f*dx + v*g*ds
> +
> +# Compute solution
> +problem = VariationalProblem(a, L, bc)
> +u = problem.solve()
> +
> +# Save solution in VTK format
> +file = File("poisson.pvd")
> +file << u
> +
> +# Plot solution
> +plot(u, interactive=True)
>
> === modified file 'source/demos/python/pde/poisson/poisson.rst'
> --- source/demos/python/pde/poisson/poisson.rst 2010-04-29 11:35:24 +0000
> +++ source/demos/python/pde/poisson/poisson.rst 2010-05-01 15:25:57 +0000
> @@ -9,4 +9,16 @@
>
> .. include:: ../../../common/pde/poisson/poisson.txt
>
> -This text is Python specific
> +This text is Python specific.
> +Here is a code snippet from the Poisson :download:`demo.py`:
> +
> +.. code-block:: python
> +
> + # Define variational problem
> + v = TestFunction(V)
> + u = TrialFunction(V)
> + f = Expression("10*exp(-(pow(x[0] - 0.5, 2) + pow(x[1] - 0.5, 2)) / 0.02)")
> + g = Expression("-sin(5*x[0])")
> + a = inner(grad(v), grad(u))*dx
> + L = v*f*dx + v*g*ds
> +
>
> === added file 'verify_code_snippets.py'
> --- verify_code_snippets.py 1970-01-01 00:00:00 +0000
> +++ verify_code_snippets.py 2010-05-01 15:25:57 +0000
> @@ -0,0 +1,138 @@
> +#!usr/bin/env python
> +
> +"""This utility script will find all *.rst files in the source/demo
> +directory and check that any code snippets highlighted by the .. code-block::
> +directive is legal in the sense that it is present in at least one of the
> +source files (.ufl, .py, .cpp) that is associated with the demo."""
> +
> +from os import chdir, path, getcwd, curdir, pardir, listdir
> +from sys import stderr
> +
> +# We currently only verifies demo code.
> +chdir(path.join("source","demos"))
> +
> +# Save current location (needed?).
> +demo_dir = getcwd()
> +
> +# We have C++ and Python versions of the demos.
> +directories = ["cpp", "python"]
> +
> +# Dictionary of code blocks that has to be checked for each subdirectory
> +# including information about file types of the source.
> +block_source = {"cpp": {"c++": ".cpp", "python": ".ufl"},
> + "python": {"python": ".py"}
> + }
> +
> +def verify_blocks(rst_file, source_files, source_dict):
> + """Check that any code blocks in the rst file is present in at least one of
> + the source files."""
> +
> + for block_type, source_type in source_dict.items():
> + # Extract code blocks from rst file.
> + blocks = get_blocks(rst_file, block_type)
> + for block in blocks:
> + # Check if block is in the list of files of correct type.
> + block_in_source(block, [sf for sf in source_files\
> + if path.splitext(sf)[-1] == source_type])
> +
> +def get_blocks(rst_file, block_type):
> + "Extract any code blocks of given type from the rst file."
> +
> + blocks = []
> +
> + # Open file and read lines.
> + f = open(rst_file, "r")
> + lines = f.read().split("\n")
> +
> + code = False
> + block = []
> + for l in lines:
> + # Get start of code block.
> + if "code-block::" in l and block_type in l:
> + code = True
> + block = []
> + continue
> + # The first line which is not an indented line terminates the code
> + # block.
> + if code and l and l[0] != " ":
> + code = False
> + # Join the block that we have and add to list of blocks.
> + # Remove any whitespace.
> + blocks.append(remove_whitespace("\n".join(block)))
> + # If code is still True, then the line is part of the code block.
> + if code:
> + block.append(l)
> +
> + # Add block of code if found at the end of the rst file.
> + if code:
> + blocks.append(remove_whitespace("\n".join(block)))
> +
> + # Close file and return blocks.
> + f.close()
> + return blocks
> +
> +def remove_whitespace(code):
> + "Remove blank lines and whitespace in front of lines."
> + return "\n".join([" ".join(l.split())\
> + for l in code.split("\n") if l != ""])
> +
> +def block_in_source(block, source_files):
> + """Check that the code block is present in at least one of
> + the source files."""
> +
> + present = False
> + code = ""
> + for sf in source_files:
> + f = open(sf, "r")
> + # Read code and remove whitespace before comparing block and code.
> + code = remove_whitespace(f.read())
> +
> + if block in code:
> + present = True
> + f.close()
> +
> + # If code is present, look no further.
> + if present:
> + return
> +
> + # Just crash the test, no need to proceed. We MUST fix the
> + if not present:
> + if not source_files:
> + raise RuntimeError("No source file!")
> +
> + print "\nError:"
> + print "\ncode block:\n", block
> + print "\ncode:\n", code
> + print "source_files:", source_files
> + print "in directory: ", getcwd()
> + raise RuntimeError("Illegal code block.")
> +
> +if __name__ == "__main__":
> +
> + print "\nTesting that all code snippets are valid.\n"
> + # Loop directories/categories/demos
> + for directory in directories:
> + chdir(directory)
> + # Get all demo categories
> + categories = [d for d in listdir(curdir) if path.isdir(d)]
> + for category in categories:
> + chdir(category)
> + demos = [d for d in listdir(curdir) if path.isdir(d)]
> + for demo in demos:
> + chdir(demo)
> + stderr.write(" "*2 + path.join(directory, category, demo))
> + # Get files in demo directory and sort in rst and source files.
> + files = listdir(curdir)
> + rst_files = [f for f in files if path.splitext(f)[-1] == ".rst"]
> + source_files = [f for f in files if path.splitext(f)[-1] in\
> + (".py", ".ufl", ".cpp")]
> + # Loop files, check if code blocks are present in source files.
> + for rst_file in rst_files:
> + verify_blocks(rst_file, source_files, block_source[directory])
> + stderr.write(", " + "OK.\n")
> + chdir(pardir)
> + chdir(pardir)
> + chdir(pardir)
> +
> + print "\nOK.\n"
> +
>
Attachment:
signature.asc
Description: Digital signature