diff --git a/code_gen/cgen.py b/code_gen/cgen.py
index 3a00f31ebe3a0f49d08d1c6dc0afdff65ae9e022..0e6fa3ba0f757f45937b4e7686c4412d841c3d33 100644
--- a/code_gen/cgen.py
+++ b/code_gen/cgen.py
@@ -11,13 +11,12 @@ from ir.lit import Lit
 from ir.loops import For, Iter, ParticleFor, While
 from ir.math import Ceil, Sqrt
 from ir.memory import Malloc, Realloc
-from ir.properties import Property, PropertyList, RegisterProperty
+from ir.properties import Property, PropertyList, RegisterProperty, UpdateProperty
 from ir.select import Select
 from ir.sizeof import Sizeof
 from ir.utils import Print
 from ir.variables import Var, VarDecl
 from sim.timestep import Timestep
-from sim.vtk import VTKWrite
 from code_gen.printer import Printer
 
 
@@ -47,6 +46,7 @@ class CGen:
         self.print("//---")
         self.print("#include \"runtime/pairs.hpp\"")
         self.print("#include \"runtime/read_from_file.hpp\"")
+        self.print("#include \"runtime/vtk.hpp\"")
         self.print("")
         self.print("using namespace pairs;")
         self.print("")
@@ -113,7 +113,7 @@ class CGen:
 
         if isinstance(ast_node, Call):
             call = self.generate_expression(ast_node)
-            self.print("{call};")
+            self.print(f"{call};")
 
         if isinstance(ast_node, For):
             iterator = self.generate_expression(ast_node.iterator)
@@ -176,18 +176,19 @@ class CGen:
         if isinstance(ast_node, Timestep):
             self.generate_statement(ast_node.block)
 
+        if isinstance(ast_node, UpdateProperty):
+            p = ast_node.property()
+
+            if p.type() != Type_Vector or p.layout() == Layout_Invalid:
+                self.print(f"ps->updateProperty({p.id()}, {p.name()});")
+            else:
+                sizes = ", ".join([str(self.generate_expression(size)) for size in ast_node.sizes()])
+                self.print(f"ps->updateProperty({p.id()}, {p.name()}, {sizes});")
+
         if isinstance(ast_node, VarDecl):
             tkw = CGen.type2keyword(ast_node.var.type())
             self.print(f"{tkw} {ast_node.var.name()} = {ast_node.var.init_value()};")
 
-        if isinstance(ast_node, VTKWrite):
-            nlocal = self.generate_expression(self.sim.nlocal)
-            npbc = self.generate_expression(self.sim.pbc.npbc)
-            nall = self.generate_expression(self.sim.nlocal + self.sim.pbc.npbc)
-            timestep = self.generate_expression(ast_node.timestep)
-            self.generate_vtk_writing(ast_node.vtk_id * 2, f"{ast_node.filename}_local", 0, nlocal, nlocal, timestep)
-            self.generate_vtk_writing(ast_node.vtk_id * 2 + 1, f"{ast_node.filename}_pbc", nlocal, nall, npbc, timestep)
-
         if isinstance(ast_node, While):
             cond = self.generate_expression(ast_node.cond)
             self.print(f"while({cond}) {{")
@@ -259,7 +260,6 @@ class CGen:
 
         if isinstance(ast_node, Lit):
             assert mem is False, "Literal is not lvalue!"
-
             if ast_node.type() == Type_String:
                 return f"\"{ast_node.value}\""
 
@@ -295,59 +295,3 @@ class CGen:
 
         if isinstance(ast_node, Var):
             return ast_node.name()
-
-    def generate_vtk_writing(self, id, filename, start, end, n, timestep):
-        # TODO: Do this in a more elegant way, without hard coded stuff
-        header = "# vtk DataFile Version 2.0\n" \
-                 "Particle data\n" \
-                 "ASCII\n" \
-                 "DATASET UNSTRUCTURED_GRID\n"
-
-        filename_var = f"filename{id}"
-        filehandle_var = f"vtk{id}"
-        self.print(f"char {filename_var}[128];")
-        self.print(f"snprintf({filename_var}, sizeof {filename_var}, \"{filename}_%d.vtk\", {timestep});")
-        self.print(f"FILE *{filehandle_var} = fopen({filename_var}, \"w\");")
-        for line in header.split('\n'):
-            if len(line) > 0:
-                self.print(f"fwrite(\"{line}\\n\", 1, {len(line) + 1}, {filehandle_var});")
-
-        # Write positions
-        self.print(f"fprintf({filehandle_var}, \"POINTS %d double\\n\", {n});")
-        self.print(f"for(int i = {start}; i < {end}; i++) {{")
-        self.print.add_ind(4)
-        self.print(f"fprintf({filehandle_var}, \"%.4f %.4f %.4f\\n\", position[i * 3], position[i * 3 + 1], position[i * 3 + 2]);")
-        self.print.add_ind(-4)
-        self.print("}")
-        self.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});")
-
-        # Write cells
-        self.print(f"fprintf({filehandle_var}, \"CELLS %d %d\\n\", {n}, {n} * 2);")
-        self.print(f"for(int i = {start}; i < {end}; i++) {{")
-        self.print.add_ind(4)
-        self.print(f"fprintf({filehandle_var}, \"1 %d\\n\", i - {start});")
-        self.print.add_ind(-4)
-        self.print("}")
-        self.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});")
-
-        # Write cell types
-        self.print(f"fprintf({filehandle_var}, \"CELL_TYPES %d\\n\", {n});")
-        self.print(f"for(int i = {start}; i < {end}; i++) {{")
-        self.print.add_ind(4)
-        self.print(f"fwrite(\"1\\n\", 1, 2, {filehandle_var});")
-        self.print.add_ind(-4)
-        self.print("}")
-        self.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});")
-
-        # Write masses
-        self.print(f"fprintf({filehandle_var}, \"POINT_DATA %d\\n\", {n});")
-        self.print(f"fprintf({filehandle_var}, \"SCALARS mass double\\n\");")
-        self.print(f"fprintf({filehandle_var}, \"LOOKUP_TABLE default\\n\");")
-        self.print(f"for(int i = {start}; i < {end}; i++) {{")
-        self.print.add_ind(4)
-        #self.print(f"fprintf({filehandle_var}, \"%4.f\\n\", mass[i]);")
-        self.print(f"fprintf({filehandle_var}, \"1.0\\n\");")
-        self.print.add_ind(-4)
-        self.print("}")
-        self.print(f"fwrite(\"\\n\\n\", 1, 2, {filehandle_var});")
-        self.print(f"fclose({filehandle_var});")
diff --git a/ir/functions.py b/ir/functions.py
index 4ae220deff22b9ec30326a0899cbec166a4f1f44..046cd77ba4a898db0c1e3ec4239db54f62f8e4ae 100644
--- a/ir/functions.py
+++ b/ir/functions.py
@@ -1,5 +1,5 @@
 from ir.bin_op import ASTTerm
-from ir.data_types import Type_Int
+from ir.data_types import Type_Int, Type_Invalid
 from ir.lit import as_lit_ast
 
 
@@ -19,8 +19,15 @@ class Call(ASTTerm):
     def type(self):
         return self.return_type
 
+    def children(self):
+        return self.params
 
 class Call_Int(Call):
     def __init__(self, sim, func_name, parameters):
         super().__init__(sim, func_name, parameters, Type_Int)
-        
+
+
+class Call_Void(Call):
+    def __init__(self, sim, func_name, parameters):
+        super().__init__(sim, func_name, parameters, Type_Invalid)
+        sim.add_statement(self)
diff --git a/ir/properties.py b/ir/properties.py
index 4be233cbb50bf522a841438de082651f154b4ade..1ff71b909fb4a333b445b83ee678160d9b26b855 100644
--- a/ir/properties.py
+++ b/ir/properties.py
@@ -114,4 +114,21 @@ class RegisterProperty(ASTNode):
         return self.sizes_list
 
     def __str__(self):
-        return f"Property<{self.prop.name()}>"
+        return f"RegisterProperty<{self.prop.name()}>"
+
+
+class UpdateProperty(ASTNode):
+    def __init__(self, sim, prop, sizes):
+        super().__init__(sim)
+        self.prop = prop
+        self.sizes_list = [as_lit_ast(sim, s) for s in sizes]
+        self.sim.add_statement(self)
+
+    def property(self):
+        return self.prop
+
+    def sizes(self):
+        return self.sizes_list
+
+    def __str__(self):
+        return f"UpdateProperty<{self.prop.name()}>"
diff --git a/runtime/pairs.hpp b/runtime/pairs.hpp
index 802eac1dc602d94591f7b8b4d4bfe4548e762a93..89b4b293d6dbb67e458a123858d650a688a501f5 100644
--- a/runtime/pairs.hpp
+++ b/runtime/pairs.hpp
@@ -70,6 +70,7 @@ public:
     std::string getName() { return name; }
     void *getPointer() { return ptr; }
     void setPointer(void *ptr_) { ptr = ptr_; }
+    void setSizes(int sx_, int sy_) { sx = sx_, sy = sy_; }
     PropertyType getType() { return type; }
     layout_t getLayout() { return layout; }
 };
@@ -103,6 +104,15 @@ private:
 public:
     PairsSim() {}
     void addProperty(Property prop) { properties.push_back(prop); }
+    void updateProperty(property_t id, void *ptr, int sx = 0, int sy = 0) {
+        auto p = std::find_if(properties.begin(), properties.end(), [id](Property p) {
+            return p.getId() == id;
+        });
+
+        PAIRS_ASSERT(p != std::end(properties));
+        p->setPointer(ptr);
+        p->setSizes(sx, sy);
+    }
 
     Property &getProperty(property_t id) {
         auto p = std::find_if(properties.begin(), properties.end(), [id](Property p) {
diff --git a/runtime/vtk.hpp b/runtime/vtk.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..1b65b49114b8eff4f985d9f97a3bfdef2893239c
--- /dev/null
+++ b/runtime/vtk.hpp
@@ -0,0 +1,58 @@
+#include <iomanip>
+#include <iostream>
+#include <fstream>
+//---
+#include "pairs.hpp"
+
+#pragma once
+
+namespace pairs {
+
+void vtk_write_data(PairsSim *ps, const char *filename, int start, int end, int timestep) {
+    std::string output_filename(filename);
+    std::ostringstream filename_oss;
+    filename_oss << filename << "_" << timestep << ".vtk";
+    std::ofstream out_file(filename_oss.str());
+    auto masses = ps->getAsFloatProperty(ps->getPropertyByName("mass"));
+    auto positions = ps->getAsVectorProperty(ps->getPropertyByName("position"));
+    const int n = end - start;
+
+    if(out_file.is_open()) {
+        out_file << "# vtk DataFile Version 2.0\n";
+        out_file << "Particle data\n";
+        out_file << "ASCII\n";
+        out_file << "DATASET UNSTRUCTURED_GRID\n";
+        out_file << "POINTS " << n << " double\n";
+
+        for(int i = start; i < end; i++) {
+            out_file << std::fixed << std::setprecision(4) << positions(i, 0) << " ";
+            out_file << std::fixed << std::setprecision(4) << positions(i, 1) << " ";
+            out_file << std::fixed << std::setprecision(4) << positions(i, 2) << "\n";
+        }
+
+        out_file << "\n\n";
+        out_file << "CELLS " << n << " " << (n * 2) << "\n";
+        for(int i = start; i < end; i++) {
+            out_file << "1 " << (i - start) << "\n";
+        }
+
+        out_file << "\n\n";
+        out_file << "CELL_TYPES " << n << "\n";
+        for(int i = start; i < end; i++) {
+            out_file << "1\n";
+        }
+
+        out_file << "\n\n";
+        out_file << "POINT_DATA " << n << "\n";
+        out_file << "SCALARS mass double\n";
+        out_file << "LOOKUP_TABLE default\n";
+        for(int i = start; i < end; i++) {
+            out_file << std::fixed << std::setprecision(4) << masses(i) << "\n";
+        }
+
+        out_file << "\n\n";
+        out_file.close();
+    }
+}
+
+}
diff --git a/sim/particle_simulation.py b/sim/particle_simulation.py
index 870985fc7f7348366a1efc5e028064b08dd2c712..ef2a6e418bca63d60a0ed64608f1fe6d01354ba2 100644
--- a/sim/particle_simulation.py
+++ b/sim/particle_simulation.py
@@ -192,12 +192,12 @@ class ParticleSimulation:
             self.kernels.lower()
         ])
 
-        timestep.add(Block(self, VTKWrite(self, self.vtk_file, timestep.timestep() + 1)))
+        timestep.add(VTKWrite(self, self.vtk_file, timestep.timestep() + 1).lower())
 
         body = Block.from_list(self, [
             self.setups.lower(),
             CellListsStencilBuild(self.cell_lists).lower(),
-            Block(self, VTKWrite(self, self.vtk_file, 0)),
+            VTKWrite(self, self.vtk_file, 0).lower(),
             timestep.as_block()
         ])
 
diff --git a/sim/properties.py b/sim/properties.py
index 79fba538412f50060d9a62831c0c069cb4bde1a6..eca36175845b14fe9cffd6f8fbb2a93b7cda35db 100644
--- a/sim/properties.py
+++ b/sim/properties.py
@@ -2,7 +2,7 @@ from functools import reduce
 from ir.data_types import Type_Float, Type_Vector
 from ir.loops import ParticleFor
 from ir.memory import Malloc, Realloc
-from ir.properties import RegisterProperty
+from ir.properties import RegisterProperty, UpdateProperty
 from ir.utils import Print
 import operator
 
@@ -27,6 +27,7 @@ class PropertiesAlloc:
 
             if self.realloc:
                 Realloc(self.sim, p, reduce(operator.mul, sizes))
+                UpdateProperty(self.sim, p, sizes)
             else:
                 Malloc(self.sim, p, reduce(operator.mul, sizes), True)
                 RegisterProperty(self.sim, p, sizes)
diff --git a/sim/resize.py b/sim/resize.py
index 4c354fa86399b3f7902d6a47e5cae296e8985e44..f862578410e845f0d7d4da522b0e13ba8aeb923a 100644
--- a/sim/resize.py
+++ b/sim/resize.py
@@ -1,8 +1,12 @@
+from functools import reduce
 from ir.branches import Filter
 from ir.data_types import Type_Int, Type_Float, Type_Vector
 from ir.loops import While
 from ir.memory import Realloc
+from ir.properties import UpdateProperty
 from ir.utils import Print
+import operator
+
 
 class Resize:
     def __init__(self, sim, capacity_var, grow_fn=None):
@@ -27,8 +31,9 @@ class Resize:
                     capacity = sum(self.sim.properties.capacities)
                     for p in properties.all():
                         if p.type() == Type_Vector:
-                            sizes = capacity * self.sim.ndims()
+                            sizes = [capacity, self.sim.ndims()]
                         else:
-                            sizes = capacity
+                            sizes = [capacity]
 
-                        Realloc(self.sim, p, sizes)
+                        Realloc(self.sim, p, reduce(operator.mul, sizes))
+                        UpdateProperty(self.sim, p, sizes)
diff --git a/sim/vtk.py b/sim/vtk.py
index 6a35b6a19caa1b61dd723b7b34e1052f0449dc13..c499726c43ca20571ae4c18e22f9fa2c090ff2b9 100644
--- a/sim/vtk.py
+++ b/sim/vtk.py
@@ -1,16 +1,22 @@
-from ir.lit import as_lit_ast
 from ir.ast_node import ASTNode
+from ir.functions import Call_Void
+from ir.lit import as_lit_ast
 
 
 class VTKWrite(ASTNode):
-    vtk_id = 0
-
     def __init__(self, sim, filename, timestep):
         super().__init__(sim)
-        self.vtk_id = VTKWrite.vtk_id
         self.filename = filename
         self.timestep = as_lit_ast(sim, timestep)
-        VTKWrite.vtk_id += 1
+
+    def lower(self):
+        nlocal = self.sim.nlocal
+        npbc = self.sim.pbc.npbc
+        self.sim.clear_block()
+        nall = nlocal + npbc
+        Call_Void(self.sim, "pairs::vtk_write_data", [self.filename + "_local", 0, nlocal, self.timestep])
+        Call_Void(self.sim, "pairs::vtk_write_data", [self.filename + "_pbc", nlocal, nall, self.timestep])
+        return self.sim.block
 
     def children(self):
         return [self.timestep]