diff --git a/hysop/backend/device/opencl/opencl_operator.py b/hysop/backend/device/opencl/opencl_operator.py
index c5222da035c3a2854ae4e48943a5ea222608593a..c53dc9f431a811ae879d76c6453f79c9f750f9a2 100644
--- a/hysop/backend/device/opencl/opencl_operator.py
+++ b/hysop/backend/device/opencl/opencl_operator.py
@@ -92,7 +92,7 @@ class OpenClOperator(ComputationalGraphOperator):
         self._check_cl_env()
     
     @debug
-    def handle_field_requirements(self):
+    def get_field_requirements(self):
         """
         called just after handle_method(), ie self.method has been set.
         topology requirements are:
@@ -129,7 +129,7 @@ class OpenClOperator(ComputationalGraphOperator):
                     cl_env=self.cl_env)
             self.output_vars[field] = topo_descriptor
 
-        super(OpenClOperator, self).handle_field_requirements()
+        return super(OpenClOperator, self).get_field_requirements()
 
     @debug
     def discretize(self):
diff --git a/hysop/backend/device/opencl/operator/directional/advection_dir.py b/hysop/backend/device/opencl/operator/directional/advection_dir.py
index 0bc30a65cd02a5d881bd5fd9e00ea1b5d5197121..4ce3c22aa2e7f603ee566748ca46cae011c7a82a 100644
--- a/hysop/backend/device/opencl/operator/directional/advection_dir.py
+++ b/hysop/backend/device/opencl/operator/directional/advection_dir.py
@@ -101,12 +101,12 @@ class OpenClDirectionalAdvection(OpenClDirectionalOperator):
         self.time_integrator = method.pop(TimeIntegrator)
 
     @debug
-    def handle_field_requirements(self):
-        super(OpenClDirectionalAdvection, self).handle_field_requirements()
-        velocity       = self.velocity
-        v_topo         = self.input_vars[velocity]
-        v_requirements = self.input_field_requirements[velocity]
-        v_dx           = v_topo.mesh.space_step
+    def get_field_requirements(self):
+        requirements = super(OpenClDirectionalAdvection, self).get_field_requirements()
+        
+        velocity               = self.velocity
+        v_topo, v_requirements = requirements.get_input_requirement(velocity)
+        v_dx                   = v_topo.mesh.space_step
 
         advection_ghosts = int(np.ceil(self.cfl * v_dx[self.direction]))
         min_ghosts = npw.integer_zeros(v_dx.shape)
@@ -114,6 +114,8 @@ class OpenClDirectionalAdvection(OpenClDirectionalOperator):
 
         v_requirements.min_ghosts = min_ghosts
 
+        return requirements
+
     @debug
     def discretize(self):
         super(OpenClDirectionalAdvection,self).discretize()
diff --git a/hysop/backend/device/opencl/operator/directional/opencl_directional_operator.py b/hysop/backend/device/opencl/operator/directional/opencl_directional_operator.py
index e4353a3fd489a6b8e1ae02052f3ec245e5082cac..c02201edab5610d39cc23a61f61c43f981c5207a 100644
--- a/hysop/backend/device/opencl/operator/directional/opencl_directional_operator.py
+++ b/hysop/backend/device/opencl/operator/directional/opencl_directional_operator.py
@@ -37,8 +37,8 @@ class OpenClDirectionalOperator(OpenClOperator):
             raise ValueError(msg)
     
     @debug
-    def handle_field_requirements(self):
-        super(OpenClDirectionalOperator, self).handle_field_requirements()
+    def get_field_requirements(self):
+        requirements = super(OpenClDirectionalOperator, self).get_field_requirements()
 
         direction = self.direction
         dim = self.splitting_dim
@@ -47,6 +47,8 @@ class OpenClDirectionalOperator(OpenClOperator):
         tstates = transposition_states[dim].all
         tstates = [ tstate for tstate in tstates if str(tstate)[-1]==sdir ]
 
-        for req in self.input_field_requirements.values():
+        for field,td,req in requirements.iter_input_requirements():
             req.transposition_states = set(tstates)
 
+        return requirements
+
diff --git a/hysop/backend/host/fortran/operator/fortran_fftw.py b/hysop/backend/host/fortran/operator/fortran_fftw.py
index f1eaa26f337c94d161e1047142ca52714a26de85..1f197df40bc8a22c02310b62f0130ceca9f0a61c 100644
--- a/hysop/backend/host/fortran/operator/fortran_fftw.py
+++ b/hysop/backend/host/fortran/operator/fortran_fftw.py
@@ -37,21 +37,23 @@ class FortranFFTWOperator(ComputationalGraphOperator):
         self.domain   = domain
         self.topology = topology
 
-    def initialize(self,topgraph_method=None):
-        super(FortranFFTWOperator,self).initialize(topgraph_method)
+    def initialize(self, **kwds):
+        super(FortranFFTWOperator,self).initialize(**kwds)
     
     @debug
-    def handle_field_requirements(self):
-        super(FortranFFTWOperator, self).handle_field_requirements()
+    def get_field_requirements(self):
+        requirements = super(FortranFFTWOperator, self).get_field_requirements()
         
-        # set can_split set to True in all directions except the contiguous one
-        for field, req in self.input_field_requirements.iteritems():
+        # set can_split to True in all directions except the contiguous one
+        # for inputs and outputs and impose no ghosts
+        for is_input, (field, td, req) in requirements.iter_requirements():
             can_split = req.can_split
             can_split[0] = False
             req.can_split  = can_split
             req.min_ghosts = npw.zeros_like(req.min_ghosts)
             req.max_ghosts = npw.zeros_like(req.min_ghosts)
 
+        return requirements
     
     @debug
     def discretize(self):
@@ -69,8 +71,8 @@ class FortranFFTWOperator(ComputationalGraphOperator):
         super(FortranFFTWOperator,self).setup(work=work)
     
     @debug
-    def finalize(self, clean_fftw_solver=False, **kargs):
-        super(FortranFFTWOperator,self).finalize(**kargs)
+    def finalize(self, clean_fftw_solver=False, **kwds):
+        super(FortranFFTWOperator,self).finalize(**kwds)
         if clean_fftw_solver:
             fftw2py.clean_fftw_solver(self.dim)
     
@@ -79,7 +81,7 @@ class FortranFFTWOperator(ComputationalGraphOperator):
         fftw specific way to discretize variables for a given
         'reference' resolution.
         It is assumed that in fft case, only one topology must be used
-        for all variables.
+        for all variables of all fortran fftw operators.
         """
         
         self._set_domain_and_tasks()
diff --git a/hysop/core/graph/computational_graph.py b/hysop/core/graph/computational_graph.py
index bf1c354be1dd503817b84b860426e00b6848c999..bb3c0cd12ae0cd436457b5482ad2718ec544259e 100644
--- a/hysop/core/graph/computational_graph.py
+++ b/hysop/core/graph/computational_graph.py
@@ -77,12 +77,11 @@ class ComputationalGraph(ComputationalGraphNode):
         ss += '\n{}\n'.format(len('== ComputationalGraph {} topology report =='.format(self.name))*'=')
         return ss
 
-    @initialized
-    def field_requirements_report(self):
+    def field_requirements_report(self, requirements):
         
         inputs = {}
         sinputs  = ''
-        for field, mreqs in self.input_field_requirements.iteritems():
+        for field, mreqs in requirements.input_field_requirements.iteritems():
             for td, reqs in mreqs.requirements.iteritems():
                 for req in reqs:
                     if __DEBUG__ or (__VERBOSE__ and not req.is_default()):
@@ -95,7 +94,7 @@ class ComputationalGraph(ComputationalGraphNode):
 
         outputs = {}
         soutputs  = ''
-        for field, mreqs in self.output_field_requirements.iteritems():
+        for field, mreqs in requirements.output_field_requirements.iteritems():
             for td, reqs in mreqs.requirements.iteritems():
                 for req in reqs:
                     if __DEBUG__ or (__VERBOSE__ and not req.is_default()):
@@ -143,64 +142,55 @@ class ComputationalGraph(ComputationalGraphNode):
         return avail_methods
 
     @debug
-    def initialize(self, topgraph_method=None, outputs_are_inputs=False):
+    def initialize(self, 
+            is_root=True,
+            topgraph_method=None, 
+            outputs_are_inputs=False,
+            **kwds):
         if self.initialized:
             return
 
-        method = super(ComputationalGraph, self).initialize(topgraph_method)
-        self._build_topologies()
-        self._build_graph(outputs_are_inputs=outputs_are_inputs)
-        self._init_base(**self._kwds)
-        
-        self.initialized = True
+        self.is_root = is_root
 
-    @debug
-    def handle_field_requirements(self):
-        super(ComputationalGraph, self).handle_field_requirements()
-        input_field_requirements  = self.input_field_requirements
-        output_field_requirements = self.output_field_requirements
+        self.pre_initialize(**kwds)
+        assert len(self.nodes) > 0, msg
+        
+        method = self._setup_method(topgraph_method)
+        self.handle_method(method)
+        
         for node in self.nodes:
             if __DEBUG__:
                 print
                 print '{} INITIALIZE'.format(node.name)
-            node.initialize(self.method)
+            node.initialize(is_root=False,
+                            outputs_are_inputs=False,
+                            topgraph_method=method,
+                            **kwds)
             if __DEBUG__:
                 print '=========================='
                 print
 
-            for ifield,ireqs in node.input_field_requirements.iteritems():
-                if not isinstance(ireqs, MultiFieldRequirements):
-                    _ireqs = ireqs
-                    ireqs = MultiFieldRequirements(ifield)
-                    ireqs.update(_ireqs)
-                if ifield in input_field_requirements:
-                    input_field_requirements[ifield].update(ireqs)
-                else:
-                    input_field_requirements[ifield] = ireqs
-
-            for ofield,oreqs in node.output_field_requirements.iteritems():
-                if not isinstance(oreqs, MultiFieldRequirements):
-                    _oreqs = oreqs
-                    oreqs = MultiFieldRequirements(ofield)
-                    oreqs.update(_oreqs)
-                if ofield in output_field_requirements:
-                    output_field_requirements[ofield].update(oreqs)
-                else:
-                    output_field_requirements[ofield] = oreqs
+        if is_root:
+            field_requirements = self.get_field_requirements()
+            field_requirements.build_topologies()
+            self._build_graph(outputs_are_inputs=outputs_are_inputs, current_level=0)
+        
+        self.initialized=True
+        
+        self.post_initialize(**kwds)
+
+        if is_root:
+            self.check()
 
     @debug
-    def _build_topologies(self):
-        if __VERBOSE__ or __DEBUG__:
-            print self.field_requirements_report()
-
-        if self.input_field_requirements:
-            for field_reqs in self.input_field_requirements.values():
-                assert isinstance(field_reqs, MultiFieldRequirements)
-                field_reqs.build_topologies()
-        if self.output_field_requirements:
-            for field_reqs in self.output_field_requirements.values():
-                assert isinstance(field_reqs, MultiFieldRequirements)
-                field_reqs.build_topologies()
+    def get_field_requirements(self):
+        requirements = super(ComputationalGraph, self).get_field_requirements()
+        for node in self.nodes:
+            node_requirements = node.get_field_requirements()
+            requirements.update(node_requirements)
+        if (self.is_root and __VERBOSE__) or __DEBUG__:
+            print self.field_requirements_report(requirements)
+        return requirements
 
     @staticmethod
     def _op_info(op, jmp=False):
@@ -216,7 +206,7 @@ class ComputationalGraph(ComputationalGraphNode):
             return ss.replace('\n','    ')
     
     @debug
-    def _build_graph(self,current_level=0,outputs_are_inputs=False,**kargs):
+    def _build_graph(self, current_level, outputs_are_inputs=False, **kwds):
         if self.graph_built:
             return
 
@@ -267,6 +257,7 @@ class ComputationalGraph(ComputationalGraphNode):
             extra_node_props = []
             
             if isinstance(node, ComputationalGraph):
+                node._build_graph(current_level=current_level+1, **kwds)
                 node_ordering   = node.sorted_nodes
                 subgraph        = node.reduced_graph
                 subgraph_ops    = subgraph.vertex_properties['operators']
@@ -507,9 +498,8 @@ class ComputationalGraph(ComputationalGraphNode):
     
         self.input_vars  = input_vars
         self.output_vars = output_vars
-
-        if (__VERBOSE__ and current_level==0) or __DEBUG__:
-            print self.topology_report()
+        
+        self._init_base(**self._kwds)
 
     @debug
     @graph_built
diff --git a/hysop/core/graph/computational_node.py b/hysop/core/graph/computational_node.py
index 34560069d15c1d04ada65d2a56f76ed049e597aa..8ca4676064765b363db6f0946323d26b6c37a27c 100644
--- a/hysop/core/graph/computational_node.py
+++ b/hysop/core/graph/computational_node.py
@@ -233,7 +233,7 @@ class ComputationalGraphNode(OperatorBase):
                 if not isinstance(v, Topology):
                     msg='Expected a Topology instance but got a {}.'.format(topo.__class__)
                     msg+='\nAll topologies are expected to be set after '
-                    msg+='ComputationalGraph.handle_field_requirements() has been called.'
+                    msg+='ComputationalGraph.get_field_requirements() has been called.'
                     raise TypeError(msg)
 
     @debug
@@ -354,7 +354,7 @@ class ComputationalGraphNode(OperatorBase):
         self.method = copy.deepcopy(method)
     
     @abstractmethod
-    def handle_field_requirements(self):
+    def get_field_requirements(self):
         """
         Called just after handle_method(), ie self.method has been set.
         Topology requirements are:
@@ -368,8 +368,8 @@ class ComputationalGraphNode(OperatorBase):
         Keys are continuous fields and values are of type
         hysop.fields.field_requirement.DiscreteFieldRequirements
         """
-        self.input_field_requirements  = {}
-        self.output_field_requirements = {}
+        from hysop.fields.field_requirements import OperatorFieldRequirements
+        return OperatorFieldRequirements()
     
     @classmethod
     def supports_multiple_topologies(cls):
@@ -401,7 +401,7 @@ class ComputationalGraphNode(OperatorBase):
         return False
    
     @debug
-    def pre_initialize(self):
+    def pre_initialize(self, **kwds):
         """
         Function called before initialization,
         can be used to alter variables set in __init__ like
@@ -411,7 +411,7 @@ class ComputationalGraphNode(OperatorBase):
         pass
 
     @debug 
-    def post_initialize(self):
+    def post_initialize(self, **kwds):
         """
         Function called after initialization,
         can be used to execute routines after handle_method has been called.
@@ -420,7 +420,7 @@ class ComputationalGraphNode(OperatorBase):
         pass
 
     @debug
-    def initialize(self, topgraph_method=None):
+    def initialize(self, topgraph_method=None, **kwds):
         """
         Initialize this node.
         
@@ -435,12 +435,12 @@ class ComputationalGraphNode(OperatorBase):
             self.pre_initialize()
             self._setup_method()
             self.handle_method()
-            self.handle_field_requirements()
+            self.get_field_requirements()
             self._initialized = True
             self.post_initialize()
         
         See ComputationalGraphNode.handle_method() to see how user method is handled.
-        See ComputationalGraphNode.handle_field_requirements() to see how topology requirements
+        See ComputationalGraphNode.get_field_requirements() to see how topology requirements
         are handled.
         
         After this method has been handled by all operators, initialization collects min and max
@@ -454,14 +454,13 @@ class ComputationalGraphNode(OperatorBase):
         if self.initialized:
             return
         
-        self.pre_initialize()
+        self.pre_initialize(**kwds)
         
         method = self._setup_method(topgraph_method)
         self.handle_method(method)
-        self.handle_field_requirements()
         self.initialized=True
 
-        self.post_initialize()
+        self.post_initialize(**kwds)
 
         return method
 
diff --git a/hysop/core/graph/computational_operator.py b/hysop/core/graph/computational_operator.py
index 82456c7abd4e59ffcdd9be80fcea78ca796e7555..89e862c72e591ef8d0ff7bcfe558efacead7479d 100644
--- a/hysop/core/graph/computational_operator.py
+++ b/hysop/core/graph/computational_operator.py
@@ -30,10 +30,10 @@ class ComputationalGraphOperator(ComputationalGraphNode):
         *An operator may support distribution along mpi processes.
          In this case supports_mpi() should return True.
          Distribution constraints along process can be specified 
-         by redefining handle_field_requirements() for inputs and outputs.
+         by redefining get_field_requirements() for inputs and outputs.
 
         *Min and max ghosts and input/output state (base or transposition state for exemple)
-         can be specified on a per variable basis in handle_field_requirements()
+         can be specified on a per variable basis in get_field_requirements()
     
     An operator may thus *override* the following class methods:
         supports_multiple_topologies()
@@ -50,7 +50,7 @@ class ComputationalGraphOperator(ComputationalGraphNode):
         handle method()  
 
     To add contraints on variables and their topologies, *override* the following method:
-        handle_field_requirements()
+        get_field_requirements()
     
     An operator has to *extend* the following abstract method:
         apply(simulation, **kwds)
@@ -80,7 +80,7 @@ class ComputationalGraphOperator(ComputationalGraphNode):
         initialize()
             pre_initialize()
             handle method()  -> self.method is set
-            handle_field_requirements() -> self.input_field_requirements it set
+            get_field_requirements() -> self.input_field_requirements it set
             self._initialized is set
             post_intialize() 
         check() (requires self.initialized to be set)
@@ -133,11 +133,9 @@ class ComputationalGraphOperator(ComputationalGraphNode):
         super(ComputationalGraphOperator,self).__init__(**kwds)
         self.input_discrete_fields  = {}
         self.output_discrete_fields = {}
-        self.input_field_requirements  = {}
-        self.output_field_requirements = {}
 
     @debug
-    def handle_field_requirements(self):
+    def get_field_requirements(self):
         """
         Called just after handle_method(), ie self.method has been set.
         Topology requirements are:
@@ -146,11 +144,6 @@ class ComputationalGraphOperator(ComputationalGraphNode):
             3) required local and global transposition state, if any. 
             4) required space (fourier, physical, ...)
             and more
-        They are stored in self.input_field_requirements and
-        self.output_field_requirements.
-
-        Keys are continuous fields and values are of type
-        hysop.fields.field_requirement.DiscreteFieldRequirements
 
         Default is Backend.HOST, no min or max ghosts, Basis.CARTESIAN and no specific
         transposition state for each input and output variables.
@@ -172,16 +165,24 @@ class ComputationalGraphOperator(ComputationalGraphNode):
                     field=field,
                     handle=topo_descriptor)
             self.output_vars[field] = topo_descriptor
-        
+
         # and we use default DiscreteFieldRequirements (ie. no min ghosts, no max ghosts,
         # can_split set to True in all directions, Basis.CARTESIAN, TranspositionState.XYZ).
+        input_field_requirements  = {}
         for field, topo_descriptor in self.input_vars.iteritems():
             req = DiscreteFieldRequirements(self, self.input_vars, field)
-            self.input_field_requirements[field] = req
+            input_field_requirements[field] = req
 
+        output_field_requirements = {}
         for field, topo_descriptor in self.output_vars.iteritems():
             req = DiscreteFieldRequirements(self, self.output_vars, field)
-            self.output_field_requirements[field] = req
+            output_field_requirements[field] = req
+        
+        requirements = super(ComputationalGraphOperator, self).get_field_requirements()
+        requirements.update_inputs(input_field_requirements)
+        requirements.update_outputs(output_field_requirements)
+        return requirements
+        
 
     @debug
     @initialized
diff --git a/hysop/core/mpi/redistribute.py b/hysop/core/mpi/redistribute.py
index bfe273e578db50cf0bd91d98d52b4bfe1a8c5d8c..f0db6039407a7b4af11d8293c0efd139e73f2303 100644
--- a/hysop/core/mpi/redistribute.py
+++ b/hysop/core/mpi/redistribute.py
@@ -182,7 +182,7 @@ class RedistributeOperator(ComputationalGraphOperator):
 
         
     @debug
-    def initialize(self, topgraph_method=None):
+    def initialize(self, topgraph_method=None, **kwds):
         super(RedistributeOperator,self).initialize(topgraph_method)
     @debug
     def discretize(self):
diff --git a/hysop/core/mpi/topology_descriptor.py b/hysop/core/mpi/topology_descriptor.py
index 3dad7d5d9a861bf8c9cd51d71d8e31f81c700751..a51ac10e7933b31d250463b8e4d72eeeb78a9cd3 100644
--- a/hysop/core/mpi/topology_descriptor.py
+++ b/hysop/core/mpi/topology_descriptor.py
@@ -154,7 +154,7 @@ class CartesianDescriptor(TopologyDescriptor):
         check_instance(field, Field)
         check_instance(handle, CartesianDescriptors)
         msg='A Cartesian topology descriptor should not contain any ghosts, '
-        msg+='they will be determined during the handle_field_requirements() in the '
+        msg+='they will be determined during the get_field_requirements() in the '
         msg+=' operator initialization step to minimize the number of topologies created.'
         msg+='\nIf you want to impose a specific topology, you can directly pass a '
         msg+='Cartesian instance into operator\'s input or output variables dictionnary instead.'
@@ -208,7 +208,7 @@ class CartesianDescriptor(TopologyDescriptor):
         Build a topology with the current TopologyDescriptor.
         Free parameters are cutdir and ghosts which are imposed
         by operators on variables and solved during operator's
-        method handle_field_requirements().
+        method get_field_requirements().
         """
         is_periodic = self.is_periodic()
         discretization = Discretization(self.discretization.resolution, ghosts)
diff --git a/hysop/fields/field_requirements.py b/hysop/fields/field_requirements.py
index e1b652bc61105dcc2b433043b741c4b424102694..271dd7c80db071d227808cde5cb2dffcee75e172 100644
--- a/hysop/fields/field_requirements.py
+++ b/hysop/fields/field_requirements.py
@@ -4,11 +4,12 @@ from hysop.deps import np, it
 from hysop.constants import Basis, transposition_states
 from hysop.tools.types import to_list, check_instance
 from hysop.tools.numpywrappers import npw
-from hysop.fields.continuous import Field
-from hysop.fields.discrete import DiscreteField
+from hysop.tools.decorators import debug
 from hysop.core.mpi.topology import Topology
 from hysop.core.mpi.topology_descriptor import TopologyDescriptor
 from hysop.core.graph.computational_node import ComputationalGraphNode
+from hysop.fields.continuous import Field
+from hysop.fields.discrete import DiscreteField
     
 def can_convert_basis_inplace(lbasis, rbasis):
     return False
@@ -77,6 +78,9 @@ class DiscreteFieldRequirements(object):
         eq &= (self.transposition_states == other.transposition_states)
         return eq
 
+    def __hash__(self):
+        return id(self.operator) ^ id(self.variables) ^ id(self.field)
+
     def __str__(self):
         def arraystr(array):
             inf = u'+\u221e'
@@ -305,3 +309,114 @@ class MultiFieldRequirements(object):
                 known_topologies.append(topo)
                 req.set_and_check_topology(topo)
 
+
+class OperatorFieldRequirements(object):
+
+    def __init__(self, input_field_requirements=None, output_field_requirements=None, **kwds):
+        super(OperatorFieldRequirements, self).__init__(**kwds)
+        
+        check_instance(input_field_requirements, dict, keys=Field, values=MultiFieldRequirements, allow_none=True)
+        self._input_field_requirements = input_field_requirements or dict()
+        
+        check_instance(output_field_requirements, dict, keys=Field, values=MultiFieldRequirements, allow_none=True)
+        self._output_field_requirements = output_field_requirements or dict()
+
+    def get_input_field_requirements(self):
+        return self._input_field_requirements
+    def get_output_field_requirements(self):
+        return self._output_field_requirements
+
+    input_field_requirements  = property(get_input_field_requirements)
+    output_field_requirements = property(get_output_field_requirements)
+    
+    def update(self, requirements):
+        check_instance(requirements, OperatorFieldRequirements)
+        self.update_inputs(requirements._input_field_requirements)
+        self.update_outputs(requirements._output_field_requirements)
+
+    def update_inputs(self, input_field_requirements):
+        check_instance(input_field_requirements, dict, keys=Field, 
+                values=(DiscreteFieldRequirements,MultiFieldRequirements))
+        for ifield,ireqs in input_field_requirements.iteritems():
+            if not isinstance(ireqs, MultiFieldRequirements):
+                _ireqs = ireqs
+                ireqs = MultiFieldRequirements(ifield)
+                ireqs.update(_ireqs)
+            if ifield in self._input_field_requirements:
+                self._input_field_requirements[ifield].update(ireqs)
+            else:
+                self._input_field_requirements[ifield] = ireqs
+
+    def update_outputs(self, output_field_requirements):
+        check_instance(output_field_requirements, dict, keys=Field, 
+                values=(DiscreteFieldRequirements,MultiFieldRequirements))
+        for ofield,oreqs in output_field_requirements.iteritems():
+            if not isinstance(oreqs, MultiFieldRequirements):
+                _oreqs = oreqs
+                oreqs = MultiFieldRequirements(ofield)
+                oreqs.update(_oreqs)
+            if ofield in self._output_field_requirements:
+                self._output_field_requirements[ofield].update(oreqs)
+            else:
+                self._output_field_requirements[ofield] = oreqs
+
+    def iter_input_requirements(self):
+        """
+        Iterates over (field, topology_descriptor, field_requirement) for all input requirements.
+        """
+        for (field,freqs) in self.input_field_requirements.iteritems():
+            freqs = freqs.requirements
+            for (td,reqs) in freqs.iteritems():
+                for req in reqs:
+                    yield field, td, req
+
+    def iter_output_requirements(self):
+        """
+        Iterates over (field, topology_descriptor, field_requirement) for all output requirements.
+        """
+        for (field,freqs) in self.output_field_requirements.iteritems():
+            freqs = freqs.requirements
+            for (td,reqs) in freqs.iteritems():
+                for req in reqs:
+                    yield (field, td, req)
+
+    def iter_requirements(self):
+        """
+        Iterates over (is_input, field, topology_descriptor, field_requirement) for all inputs and outputs.
+        """
+        it0 = it.izip_longest((True,),  self.iter_input_requirements())
+        it1 = it.izip_longest((False,), self.iter_output_requirements())
+        return it.chain(it0, it1)
+
+    def get_input_requirement(self, field):
+        """
+        Get unique requirement and topology descriptor for given field, if it exists.
+        This is a facility for ComputationalGraphOperators to retrieve their unique per field requirements.
+        If field is not an hysop.fields.continuous.Field, a TypeError is raised.
+        If field is not known, an Attribute error is raised.
+        If multiple topology_descriptors or requirements are present (ie. there is not unicity),
+        raise a RuntimeError.
+        """
+        check_instance(field, Field)
+        if field not in self._input_field_requirements:
+            msg='No requirements found for field {}.'.format(field.name)
+            raise AttributeError(msg)
+        freqs = self._input_field_requirements[field].requirements
+        if len(freqs.keys())>1:
+            msg='Multiple topology descriptors are present for field {}.'.format(field.name)
+            raise RuntimeError(msg)
+        td = freqs.keys()[0]
+        reqs = freqs[td]
+        if len(reqs)>1:
+            msg='Multiple requirements are present for field {}.'.format(field.name)
+            raise RuntimeError(msg)
+        return (td, next(iter(reqs)))
+
+    @debug
+    def build_topologies(self):
+        if self._input_field_requirements:
+            for field_reqs in self.input_field_requirements.values():
+                field_reqs.build_topologies()
+        if self._output_field_requirements:
+            for field_reqs in self.output_field_requirements.values():
+                field_reqs.build_topologies()
diff --git a/hysop/operator/analytic.py b/hysop/operator/analytic.py
index 577c06bf6633d7717bf85d3d4300881d6722052d..1d14831dac07db0943f783dc07fad50fb082cef9 100644
--- a/hysop/operator/analytic.py
+++ b/hysop/operator/analytic.py
@@ -57,8 +57,8 @@ class Analytic(ComputationalGraphOperator):
 
 
     @debug
-    def initialize(self, topgraph_method=None):
-        super(Analytic,self).initialize(topgraph_method)
+    def initialize(self, **kwds):
+        super(Analytic,self).initialize(**kwds)
 
     @debug
     def discretize(self):
diff --git a/hysop/operator/hdf_io.py b/hysop/operator/hdf_io.py
index d2da86bf99d3fbb6ae1bb70a24977543370b8125..4a2e2671913b8b46a50041a548dd2605965a8dd8 100755
--- a/hysop/operator/hdf_io.py
+++ b/hysop/operator/hdf_io.py
@@ -104,8 +104,8 @@ class HDF_IO(ComputationalGraphOperator):
         # File Object that holds hdf file
         self._hdf_file = None
 
-    def initialize(self):
-        super(HDF_IO, self).initialize()
+    def initialize(self, **kwds):
+        super(HDF_IO, self).initialize(**kwds)
     
     def discretize(self):
         if not self.initialized:
diff --git a/hysop/problem.py b/hysop/problem.py
index 8de18fda40fb4038c23fb75ae25767cdbccec13f..745b13316327134d048bc1c9fd8ed5c2f27cc889 100644
--- a/hysop/problem.py
+++ b/hysop/problem.py
@@ -16,8 +16,6 @@ class Problem(ComputationalGraph):
     def build(self):
         vprint('\nInitializing problem...')
         self.initialize(outputs_are_inputs=True, topgraph_method=None)
-        vprint('\nChecking problem...')
-        self.check()
         vprint('\nDiscretizing problem...')
         self.discretize()
         vprint('\nGetting work properties...')