diff --git a/docs/source/bladed/Bladed_airfoil.png b/docs/source/bladed/Bladed_airfoil.png
new file mode 100644
index 0000000000000000000000000000000000000000..25bda289fe7e84f4518224469f4d3451a829c71d
Binary files /dev/null and b/docs/source/bladed/Bladed_airfoil.png differ
diff --git a/docs/source/bladed/Bladed_st_centers.png b/docs/source/bladed/Bladed_st_centers.png
new file mode 100644
index 0000000000000000000000000000000000000000..30772804ba8f5b09a8e989b4f9b04077af342aa1
Binary files /dev/null and b/docs/source/bladed/Bladed_st_centers.png differ
diff --git a/docs/source/bladed/Bladed_turbine_coord.png b/docs/source/bladed/Bladed_turbine_coord.png
new file mode 100644
index 0000000000000000000000000000000000000000..e9a897791ab413d694824edc4f08885338ad9259
Binary files /dev/null and b/docs/source/bladed/Bladed_turbine_coord.png differ
diff --git a/docs/source/bladed/HAWC2_c2_def_ccord.png b/docs/source/bladed/HAWC2_c2_def_ccord.png
new file mode 100644
index 0000000000000000000000000000000000000000..f940380b8f03988a8a653763efd800f9c7ca0722
Binary files /dev/null and b/docs/source/bladed/HAWC2_c2_def_ccord.png differ
diff --git a/docs/source/bladed/HAWC2_st_centers.png b/docs/source/bladed/HAWC2_st_centers.png
new file mode 100644
index 0000000000000000000000000000000000000000..1d0430f2be5ac61be4f3b8308712411049344d67
Binary files /dev/null and b/docs/source/bladed/HAWC2_st_centers.png differ
diff --git a/docs/source/bladed/HAWC2_turbine_coord.png b/docs/source/bladed/HAWC2_turbine_coord.png
new file mode 100644
index 0000000000000000000000000000000000000000..34e45d8e99dbb916aa3c564c721427e8cd4fabaf
Binary files /dev/null and b/docs/source/bladed/HAWC2_turbine_coord.png differ
diff --git a/docs/source/bladed/bladed2hawc.rst b/docs/source/bladed/bladed2hawc.rst
new file mode 100644
index 0000000000000000000000000000000000000000..20f4faaa4d1e51bd10e94010180a6afcd3f4e325
--- /dev/null
+++ b/docs/source/bladed/bladed2hawc.rst
@@ -0,0 +1,185 @@
+********************************
+BLADED to HAWC2 model conversion
+********************************
+
+**BLADED** is a tool developed by DNV, and ``wetb`` contains a basic reader that
+can interpret a BLADED project file (.prj) and convert the data structures into
+an equivalent set of **HAWC2** input files (htc, st, ae, pc).
+
+
+================================
+API and workflow
+================================
+
+---------------------------------
+Read BLADED project file
+---------------------------------
+
+The input from a Bladed model is given in a project file (*prj*) and is formatted
+in the XML definition. Within this file the core BLADED inputs are given in the
+CDATA field and which according to the XML standards refer to Character Data,
+see also `here <https://www.w3resource.com/xml/CDATA-sections.php>`_ and `here
+<https://en.wikipedia.org/wiki/CDATA>`_ for a more detailed technical description.
+Within the CDATA field a custom BLADED type markup definition is used. The ``wetb``
+reader includes an interpreter for this custom BLADED markup and outputs this
+data structure to the user as a nested dictionary, and which allows easy access
+to all the different key/value pairs defined in the BLADED CDATA field. This
+nested dictionary structure is accessible via the variable
+``wetb.bladed.readprj.ReadBladedProject.bd``.
+
+Outside the CDATA field the XML data is parsed via the ``lxml`` Python package,
+and the entire XML object ``lxml.objectify.fromstring(str)`` is exposed to the user
+via the ``wetb.bladed.readprj.ReadBladedProject.xmlroot`` variable.
+
+
+In ``wetb` the
+project file can be read using the following::
+
+     from wetb.bladed.readprj import ReadBladedProject
+     prj = ReadBladedProject('my_bladed_project_file.prj')
+     # XML object tree (and lxml data object)
+     prj.xmlroot
+     # CDATA field as nested dictionary
+     prj.bd
+
+
+A convenience function ``wetb.bladed.readprj.ReadBladedProject.get_key`` is also
+available to extract a ``numpy`` array, for example as follows::
+
+     from wetb.bladed.readprj import ReadBladedProject
+     prj = ReadBladedProject('my_bladed_project_file.prj')
+     # the following keys contain a data array
+     data_arr = prj.get_key('BSTIFFMB', 'EIFLAP')
+     # which is the similar calling (but excludes data conversion to int/float)
+     prj.bd['BSTIFFMB']['EIFLAP']
+     # if a key contains a section with sub-keys, a dictionary is returned:
+     data_dict = prj.get_key('BSTIFFMB')
+     # and is similar to
+     prj.bd['BSTIFFMB']
+
+
+---------------------------------
+Convert BLADED project file to HAWC2
+---------------------------------
+
+The class ``wetb.bladed.prj2hawc.Convert2Hawc`` will convert a Bladed project
+file into a set of HAWC2 input files. This process assumes that a standard
+3 bladed upwind turbine configuration is used, and a generic HAWC2 `htc template
+file  <https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/-/blob/master/wetb/bladed/template.htc>`_
+serves as the starting point for the conversion process. Note that the converter
+class ``wetb.bladed.prj2hawc.Convert2Hawc`` inherits from
+``wetb.bladed.readprj.ReadBladedProject``, and hence will first read the Bladed
+project file::
+
+    import os
+    import urllib.request
+    import shutil
+    from wetb.bladed.prj2hawc import Convert2Hawc
+    # download the htc template file,
+    url = 'https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox/-/'
+    url += 'raw/master/wetb/bladed/template.htc'
+    fname_tmpl = '/path/to/my/template.htc'
+    with urllib.request.urlopen(url) as response, open(fname_tmpl, 'wb') as fout:
+        shutil.copyfileobj(response, fout)
+    # file name of the Bladed project file
+    fprj = '/path/to/my/bladed.prj'
+    # initiate the project converter object, will first read the prj file (see above)
+    prj = Convert2Hawc(fprj)
+    # convert to the HAWC2 formats: htc, ae, pc and st files
+    fname_htc = fname_tmpl.replace('template.htc', 'bladed-to-hawc2.htc')
+    prj.convert(fname_htc)
+    # note that the ae, pc and st files will be saved in the same directory as
+    # fname_htc, with .htc replaced by .ae, .pc, .st etc.
+
+
+================================
+Theoretical background
+================================
+
+---------------------------------
+Coordinate systems
+---------------------------------
+
+The coordinate systems used in both codes are different. Note that in HAWC2
+coordinate systems of general bodies are defined by the users. However,
+the HAWC2 global and blade cross-section coordinate systems are predetermined,
+and they differ from Bladed in the following manner:
+
+* Global Bladed *X* axis is positive pointing downwind whereas in HAWC2 the
+  global *Y* direction is positive in the downwind direction.
+
+* The HAWC2 global *Z* direction is in the same direction as the gravity vector
+  (positive down), while it is the opposite in Bladed (positive up).
+
+* The Bladed cross-section coordinate system is rotated 90 degrees around *Z* wrt HAWC2.
+
+The figures below illustrate clearly the HAWC2 and Bladed coordinate systems.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+Bladed coordinate systems
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. figure:: Bladed_turbine_coord.png
+   :width: 200
+   :alt: bladed_turbine_coord
+
+   Bladed coordinate system, rotor rotation and radius definition.
+
+.. figure:: Bladed_st_centers.png
+   :width: 400
+   :alt: bladed_st_coord
+
+   Bladed cross-section structural centers, half chord location and structural pitch definition.
+
+.. figure:: Bladed_airfoil.png
+   :width: 400
+   :alt: bladed_airfoil_coord
+
+   Bladed airfoil geometric positioning along the blade.
+
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+HAWC2 coordinate systems
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+.. figure:: HAWC2_turbine_coord.png
+    :width: 200
+    :alt: hawc2_turbine_coord
+
+    HAWC2 global, tower, shaft, hub, blade-i and meteorological coordinate systems.
+
+.. figure:: HAWC2_st_centers.png
+    :width: 400
+    :alt: hawc2_st_ccord
+
+    HAWC2 cross-section structural centers, half chord location and structural pitch definition.
+
+.. figure:: HAWC2_c2_def_ccord.png
+    :width: 400
+    :alt: hawc2_airfoil_coord
+
+    HAWC2 airfoil positioning in blade body coordinates and aerodynamic pitch given as in the *htc* file *c2_def* section.
+
+
+---------------------------------
+Cross-sectional parameters
+---------------------------------
+
+Bladed uses isotropic material definitions for all bodies and for the HAWC2
+conversion the same isotropic assumption is used. Since the HAWC2 *st* file definition
+splits the Young's (*E*) and shear modulus (*G*) from the actual stiffness terms, and Bladed
+defines the actual stiffness values (meaning the product of *EI* etc), the
+corresponding HAWC2 *st* input simply assumes a value for *E* and *G*, and
+specifies the inertia such that the product (i.e. stiffness) is correct.
+
+Bladed defines a mass polar moment of inertia in combination with the ratio
+between the mass radii of gyration around the airfoil's center of mass, while
+in HAWC2 the radii of gyration in *X* and *Y* direction are given wrt the elastic
+center.
+
+
+---------------------------------
+References
+---------------------------------
+
+[1] `HAWC2 User Manual v12.8 <http://tools.windenergy.dtu.dk/HAWC2/manual/>`_
+
+[2] Bladed 4.6 Manual
+
diff --git a/docs/source/index.rst b/docs/source/index.rst
index d13f3e8dd93bb6bc333145efbce889d7dec93ec0..b3c1c44073bb7bd66edc49d0bb4328d039931319 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -13,7 +13,7 @@ tab on the left to install the code and get started.
 
 Source code repository (and issue tracker):
     https://gitlab.windenergy.dtu.dk/toolbox/WindEnergyToolbox
-    
+
 License:
     GPLv3_
 
@@ -25,4 +25,6 @@ Contents:
 
         installation
         fatigue_tools/fatigue
-        hawc2/hawc2
\ No newline at end of file
+        hawc2/hawc2
+        bladed/bladed2hawc
+
diff --git a/wetb/bladed/prj2hawc.py b/wetb/bladed/prj2hawc.py
new file mode 100644
index 0000000000000000000000000000000000000000..803930e730af7afd48f41c3e02083807120a0c1c
--- /dev/null
+++ b/wetb/bladed/prj2hawc.py
@@ -0,0 +1,847 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jun 23 11:20:28 2021
+
+@author: dave
+"""
+
+import os
+from os.path import join as pjoin
+
+import numpy as np
+import pandas as pd
+
+# from wetb.prepost import misc
+from wetb.hawc2 import (HTCFile, AEFile, PCFile, StFile)
+
+from readprj import ReadBladedProject
+
+
+# TODO: move to misc?
+def get_circular_inertia(d1, t, m):
+    d2 = d1 - 2*t
+    A = np.pi/4*(d1**2-d2**2)
+    I_g = np.pi/64*(d1**4-d2**4)
+    I_m = I_g/A*m
+    return A,I_g,I_m
+
+
+# TODO: move to HTCFile?
+def add_c2_arr_htc(htc, c2_arr, body):
+    """add a c2_def in the form of an array to a htc c2_def section. Needs to
+    be an existing body, and the current c2_def will be overwritten.
+    """
+    nr_nodes = c2_arr.shape[0]
+    c2_def = htc['new_htc_structure'].get_subsection_by_name(body)['c2_def']
+
+    keys = ['sec'] + [f'sec__{i}' for i in range(2, nr_nodes+1)]
+
+    c2_def['nsec'].values[0] = nr_nodes
+    for i, key in enumerate(keys):
+        # control the formatting, otherwise it looks very messy in the htc file
+        # this we do by converting the values to strings
+        vals_fmt = [f'{k: 15.07f}' for k in c2_arr[i,:].tolist()]
+        # node nr is stripped from leading spaces, so it doesn't help adding them
+        values = [i+1] + vals_fmt
+        if key in c2_def:
+            c2_def[key].values[:] = values[:]
+        else:
+            c2_def.add_line(name=key, values=values)
+
+    return htc
+
+
+# TODO: move to HTCFile?
+def get_c2def(htc, body_name):
+    """
+    """
+
+    # select the c2def section from the shaft
+    c2_def = htc['new_htc_structure'].get_subsection_by_name(body_name)['c2_def']
+    # safe all c2_def positions in one array
+    c2_arr = np.zeros((len(c2_def.keys())-1,4))
+    # iterate over all nsec lines, but ignore the line that gives the number of points
+    for i, sec in enumerate(c2_def.keys()[1:]):
+        c2_arr[i,:] = c2_def[sec].values[1:]
+
+    return pd.DataFrame(c2_arr, columns=['x', 'y', 'z', 'twist'])
+
+
+class Convert2Hawc(ReadBladedProject):
+    """Based on the BLADED user manual v4.8
+    """
+
+    def __init__(self, fname):
+        super().__init__(fname)
+
+    def get_pc(self, setname_filter=None):
+        # ---------------------------------------------------------------------
+        # we ignore the airfoils blocks at the start of the ADAT sub-section
+        # ---------------------------------------------------------------------
+        # nr_airfoils = prj.get_key('ADAT', 'NFOILS')[0,0]
+        # airfoil_keys = ['NFOIL', 'FTYPE', 'NTHICK', 'NREYN']
+        # airfoils = {}
+        # for k in range(nr_airfoils):
+        #     key_app = ''
+        #     if k > 0:
+        #         key_app = f'__{k+1}'
+        #     airfoils[f'NFOIL_{k+1}'] = {}
+        #     for key in airfoil_keys:
+        # ---------------------------------------------------------------------
+
+        # total number of pc sets
+        nsets = self.get_key('ADAT', 'NSETS')[0,0]
+        key_app = [''] + [f'__{k}' for k in range(2, nsets+1)]
+
+        # FIXME: are all sets always named consistantly? Meaning only the
+        # thickness changes in the setname, and the rest remains the same?
+        # as a work-around: ignore sets that contains setname_filter in SETNAME
+        if setname_filter is not None:
+            drop = []
+            for i, ka in enumerate(key_app):
+                setname = self.get_key('ADAT', f'SETNAME{ka}')[0,0]
+                if setname.find(setname_filter) > -1:
+                    drop.append(ka)
+            key_app = set(key_app) - set(drop)
+            # update nsets
+            nsets = len(key_app)
+
+        # initiate PCFile objects
+        pc = PCFile()
+        tc_arr = np.ndarray((nsets), dtype=np.float32)
+        pc_lst = []
+
+        for i, ka in enumerate(key_app):
+
+            # and assure cm is around quarter chord point
+            assert self.get_key('ADAT', 'XA')[0,0]==25
+
+            # prj.get_key('ADAT', f'SETNAME{ka}')
+            # prj.get_key('ADAT', f'SETNB{ka}')
+            # prj.get_key('ADAT', f'COMMENTS{ka}')
+            # prj.get_key('ADAT', f'DATE{ka}')
+            # prj.get_key('ADAT', f'REYN{ka}')
+            # prj.get_key('ADAT', f'DEPL{ka}')
+            # prj.get_key('ADAT', f'NALPHA{ka}')
+            # prj.get_key('ADAT', f'NVALS{ka}')
+
+            tc_arr[i] = self.get_key('ADAT', f'THICK{ka}')
+            shape = (self.get_key('ADAT', f'NALPHA{ka}')[0,0], 4)
+            pcs = np.ndarray(shape, dtype=np.float32)
+            pcs[:,0] = self.get_key('ADAT', f'ALPHA{ka}')[0,:]
+            pcs[:,1] = self.get_key('ADAT', f'CL{ka}')[0,:]
+            pcs[:,2] = self.get_key('ADAT', f'CD{ka}')[0,:]
+            pcs[:,3] = self.get_key('ADAT', f'CM{ka}')[0,:]
+            pc_lst.append(pcs)
+
+        # in BGEOM the airfoil number is referred to and not the thickness
+        # sort properly on thickness
+        isort = tc_arr.argsort()
+        pc.pc_sets = {1:(tc_arr[isort], [pc_lst[k] for k in isort])}
+
+        return pc
+
+    def get_ae(self):
+        # BGEOMMB defines for each element the start and end point. We only
+        # need half that of course.
+        chord = self.get_key('BGEOMMB', 'CHORD')[0,0::2]
+        # FIXME: is it radius or curved lenght
+        radius = self.get_key('BGEOMMB', 'RJ')[0,0::2]
+        thickness = self.get_key('BGEOMMB', 'BTHICK')[0,0::2]
+        # FIXME: multiple pc sets can be defined but are ignored for now.
+        pc_set_id = np.ones(chord.shape)
+
+        ae = AEFile()
+        ae.add_set(radius, chord, thickness, pc_set_id, set_id=None)
+
+        return ae
+
+    def get_blade_c2_def(self):
+
+        # BLADENAME
+        # DISTMODE	RJ
+        # NBE	100
+        # FOIL
+        # MOVING
+
+        # CE_X
+        # CE_Y
+        diam = self.get_key('RCON', 'DIAM')[0,0]
+        cone = self.get_key('RCON', 'CONE')[0,0]
+        tilt = self.get_key('RCON', 'TILT')[0,0]
+
+        # in BLADED all is wrt LE, so we need chord
+        chord = self.get_key('BGEOMMB', 'CHORD')[0,0::2]
+
+        # c2_def = htc['new_htc_structure'].get_subsection_by_name('blade1')['c2_def']
+        twist = self.get_key('BGEOMMB', 'TWIST')[0,0::2]
+
+        # FIXME: what is the difference between RJ and DIST?
+        # radius can be given eiter as curved length or radius
+        # Distance: This can be entered as a distance along the blade or as a
+        # distance along the blade root Z-axis. Select the appropriate option
+        # at the base of the screen.
+        dist = self.get_key('BGEOMMB', 'DIST')[0,0::2]
+        rj = self.get_key('BGEOMMB', 'RJ')[0,0::2]
+        # reference frame is EC, that seems to be indicated on the plots of the
+        # blade rotor coordinates/pitch/axis tc (fig 4-1 and 4-2)
+        ref_x = self.get_key('BGEOMMB', 'REF_X')[0,0::2]
+        ref_y = self.get_key('BGEOMMB', 'REF_Y')[0,0::2]
+        # EC wrt to LE in percentage of chord
+        ce_x = self.get_key('BGEOMMB', 'CE_X')[0,0::2]
+        ce_y = self.get_key('BGEOMMB', 'CE_Y')[0,0::2]
+
+        # HAWC2 variables
+        theta = twist*-1
+        # theta_d = theta*180/np.pi
+        ea_x = (50-ce_y)*0.01*chord
+        ea_y = ce_x*0.01*chord
+
+        # safe all c2_def positions in one array
+        c2_arr = np.zeros((len(twist),4))
+        c2_arr[:,0] = -1*(ref_y + ((ea_x*np.cos(theta) - ea_y*np.sin(theta))))
+        c2_arr[:,1] =    (ref_x - ((ea_x*np.sin(theta) + ea_y*np.cos(theta))))
+        # assume DIST is curved length
+        c2_arr[:,2] = rj #dist
+        c2_arr[:,3] = theta*180/np.pi
+
+        return c2_arr
+
+    def get_blade_st(self):
+        # BMASSMB
+        # BSTIFFMB
+
+        # in HAWC2 structural pitch is relative to the twist
+        twist = self.get_key('BGEOMMB', 'TWIST')[0,0::2]
+        dist = self.get_key('BGEOMMB', 'DIST')[0,0::2]
+        chord = self.get_key('BGEOMMB', 'CHORD')[0,0::2]
+        thickness = self.get_key('BGEOMMB', 'BTHICK')[0,0::2]
+
+        # CG location, in percentage chord wrt LE
+        cm_x = self.get_key('BMASSMB', 'CM_X')[0,0::2]
+        cm_y = self.get_key('BMASSMB', 'CM_Y')[0,0::2]
+        mass = self.get_key('BMASSMB', 'MASS')[0,0::2]
+        siner = self.get_key('BMASSMB', 'SINER')[0,0::2]
+
+        # Radii of gyration ratio: the radius of gyration of mass about y_m
+        # divided by the radius of gyration of mass about x_m. This defaults to
+        # the relative profile thickness but can be over-written by un-checking
+        # the “Use default radii of gyration ratio” checkbox.
+        rgratio = self.get_key('BMASSMB', 'RGRATIO')[0,0::2]
+        # FIXME: DEF_RGRATIO but which value belongs to which option?
+        # assume 0 means "default is off"
+        def_rgratio = self.get_key('BMASSMB', 'DEF_RGRATIO')[0,0]
+
+        # FIXME: BETA_M: figure 3-2 from v4.8: mass axis orientation, radians?
+        beta_m = self.get_key('BMASSMB', 'BETA_M')[0,0::2]
+        # Mass axis orientation: the orientation of the principle axis of inertia.
+        # This defaults to the orientation of aerodynamic twist, but can be
+        # over-written by un-checking the “Use default mass axis orientation”
+        # checkbox. (See diagram below)
+        # FIXME: DEF_BETA_M but which value belongs to which option?
+        # assume 0 means "default is off"
+        def_beta_m = self.get_key('BMASSMB', 'DEF_BETA_M')[0,0]
+
+        # DEF_RGRATIO	0
+        # DEF_BETA_M	0
+
+        # RADPOS
+        # PITCHPOS
+
+        # DEF_RGRATIO	0
+        # DEF_BETA_M	0
+        # ICEDBLADES	 0, 0, 0
+        # ICEDENSITY	 700
+        # TIPCHORD	 0
+        # NPOINT	3
+        # RADPOS	 .2, 30.12345, 40.12345
+        # PITCHPOS	 .2, 30.1, 40.1
+        # PM_X	 0, 0, 0
+        # PM_Y	 20, 10, 20
+        # PMASS	 1000, 30, 1
+
+        # elastic axis, in percentage chord wrt LE
+        ce_x = self.get_key('BGEOMMB', 'CE_X')[0,0::2]
+        ce_y = self.get_key('BGEOMMB', 'CE_Y')[0,0::2]
+
+        # 3.5 Blade stiffness distribution (page 19)
+        # The stiffness must be defined about the principal axis of inertia at
+        # each blade station (see 3.1). The stiffness is the product of Young’s
+        # Modulus for the material and the second moment of area for the xp or
+        # yp directions as appropriate. The principal axis orientation is defined
+        # as an input, and defaults to the aerodynamic twist. In this case it is
+        # assumed to be parallel and perpendicular to the chord line. If the
+        # principal axis orientation is different from the aerodynamic twist, click
+        # the Use default principal axis orientation to off. (see diagram below)
+        eiflap = self.get_key('BSTIFFMB', 'EIFLAP')[0,0::2]
+        eiedge = self.get_key('BSTIFFMB', 'EIEDGE')[0,0::2]
+        beta_s = self.get_key('BSTIFFMB', 'BETA_S')[0,0::2]
+        gj = self.get_key('BSTIFFMB', 'GJ')[0,0::2]
+        cs_x = self.get_key('BSTIFFMB', 'CS_X')[0,0::2]
+        cs_y = self.get_key('BSTIFFMB', 'CS_Y')[0,0::2]
+        gaflap = self.get_key('BSTIFFMB', 'GAFLAP')[0,0::2]
+        gaedge = self.get_key('BSTIFFMB', 'GAEDGE')[0,0::2]
+        # FIXME: DEF_BETA_S probably says what the frame of reference is
+        # assume 0 means "default is off"
+        # self.get_key('BMASSMB', 'DEF_BETA_S')[0,0::2]
+
+        # for plotting purposes
+        sel = beta_m < -1
+        beta_m[sel] += np.pi
+        sel = beta_s < -1
+        beta_s[sel] += np.pi
+
+        # calculate the curved length
+        # c2_arr = self.get_blade_c2_def()
+        # curved_len_arr = curved_length(c2_arr)
+
+        ea_x = (50-ce_y)*0.01*chord
+        ea_y = ce_x*0.01*chord
+        cg_x = (50-cm_y)*0.01*chord
+        cg_y = cm_x*0.01*chord
+
+        # mass moments
+        Ipm_y = siner + (mass*(cg_x-ea_x)**2)
+        ri_y = np.sqrt( (Ipm_y / (1+rgratio**2)) / mass )
+        ri_x = rgratio * ri_y
+        # in BLADED rgratio = y/x, but in HAWC2 it x=y so we swap them
+
+        # just choose E, G so the rest follows
+        E, G = 1e10, 1e09
+        # however, we don't know EA (probably because stiff?), so assume A is
+        # a full box based on chord length and maximum airfoil thickness
+        # this will make the extensional stiffness EA quite large, but the user
+        # would still end up with a physical meaningful value
+        A = chord*chord*thickness/100
+
+        starr = np.ndarray((len(dist),19))
+        starr[:,0] = dist
+        starr[:,1] = mass
+        starr[:,2] = cg_x
+        starr[:,3] = cg_y
+        # radius of gyration
+        starr[:,4] = ri_x
+        starr[:,5] = ri_y
+        # shear center
+        starr[:,6] = (50-cs_y)*0.01*chord
+        starr[:,7] = cs_x*0.01*chord
+        # E, G: choose
+        starr[:,8] = E
+        starr[:,9] = G
+        starr[:,10] = eiflap/E
+        starr[:,11] = eiedge/E
+        starr[:,12] = gj/G
+        # shear factor
+        starr[:,13] = gaflap/(G*A)
+        starr[:,14] = gaedge/(G*A)
+        starr[:,15] = A
+        starr[:,16] = -1*(beta_s - twist) # structural pitch
+        starr[:,17] = ea_x
+        starr[:,18] = ea_y
+
+        st = StFile()
+        st.main_data_sets = {1:{1:starr}}
+        # st.cols = wetb.hawc2.st_file.stc.split()
+        return st
+
+    def get_tower_c2_def_st(self):
+        """Ignores nodes that are not at the centerline
+
+        Returns
+        -------
+        c2_arr : TYPE
+            DESCRIPTION.
+        st : TYPE
+            DESCRIPTION.
+
+        """
+
+        t_n_e = int(self.get_key('TGEOM', 'NTE'))
+        t_n_n = int(self.get_key('TGEOM', 'NTS'))
+        t_el_mat = self.get_key('TGEOM', 'ELSTNS')
+        t_n_coord = self.get_key('TGEOM', 'TCLOCAL')
+        # tdiam = self.get_key('TGEOM', 'SEAL')
+        # tdiam = self.get_key('TGEOM', 'HYDRO')
+        towmgt = self.get_key('TGEOM', 'TOWMGT')
+        # MATERIAL, NOMATS
+        material = self.get_key('TMASS', 'MATERIAL')[0,0::2]
+        nomats = self.get_key('TMASS', 'NOMATS')
+
+        # Index of tower nodes (nodes at zero x-y positions)
+        t_a = np.where((abs(t_n_coord[:,0])+abs(t_n_coord[:,1])) == 0)[0]
+        t_nodes = t_n_coord[t_a]
+        # sort index according to z position of the nodes
+        n_ind = t_a[np.argsort(t_nodes[:,2])]
+        t_nodes = t_n_coord[n_ind]
+        # Index for tower elemetns
+        # Elemet indexes which does not contain both tower nodes
+        ind_not = [i for i,j in enumerate(t_el_mat) if not (j[0]-1) in n_ind
+                   or not (j[1]-1) in n_ind]
+        # The elemetn indexes excluding the ind_not
+        ind_init = np.array([i for i in range(t_el_mat.shape[0]) if not i in ind_not])
+        sort_el = []
+        for i in n_ind[:-1]:
+            sort_el.append(np.where(t_el_mat[ind_init][:,0] == i+1)[0][0])
+        ind_el = ind_init[sort_el]
+
+        # safe all c2_def positions in one array
+        c2_arr = np.zeros((t_nodes.shape[0],4))
+        c2_arr[:,0:2] = t_nodes[:,:-1].copy()
+        c2_arr[:,2] = -t_nodes[:,-1] + t_nodes[0,-1] # It is minus for HAWC2 model
+        c2_arr[:,3] = 0.0
+        # element properties
+        t_d =  self.get_key('TGEOM', 'TDIAM')[ind_el]
+        material = self.get_key('TMASS', 'MATERIAL')[0,0::2][ind_el]
+        t_thick = self.get_key('TMASS', 'WALLTHICK')[ind_el]
+        towmgt = self.get_key('TGEOM', 'TOWMGT')[ind_el]
+        # Mass
+        t_m = self.get_key('TMASS', 'TOWM')[ind_el]
+        t_p_m = self.get_key('TMASS', 'TOWPMI')[ind_el] # point mass for elements and nodes
+        t_flood = self.get_key('TMASS', 'FLOODED')[ind_el]
+        # material props from prj file
+        name_mat = np.unique(material)
+        mat_prop = {}
+        for i in name_mat:
+            mat_prop[i] = self.get_key('TMASS', "%s"%i) # rho, E, G
+
+        t_mat = np.array([mat_prop[i][0] for i in material])
+
+        if np.sum(t_thick[1:,0] - t_thick[:-1,1]) > 1e-9:
+            print('Diameters are not continous along the tower')
+        if (name_mat.shape[0] > 1):
+            print('There are %i materials in tower!' %name_mat.shape[0])
+        d = np.zeros(t_d.shape[0]+1)
+        t = np.zeros(t_thick.shape[0]+1)
+        mat = np.zeros((t_mat.shape[0]+1,t_mat.shape[1]))
+        d[1:] = t_d[:,1]
+        t[1:] = t_thick[:,1]
+        mat[1:,:] = t_mat.copy()
+        d[0] = t_d[0,1]
+        t[0] = t_thick[0,1]
+        mat[0,:] = t_mat[0,:].copy()
+
+        A,I_g,I_m = get_circular_inertia(d,t,mat[:,0])
+        # FIXME: MAYBE ANOTHER FIX FOR DIFFERENT MATERIALS
+        # return c2_arr
+        starr = np.zeros((c2_arr.shape[0],19))
+        starr[:,0] = -c2_arr[:,2] #
+        starr[:,1] = A*mat[:,0]
+        starr[:,2] = 0.0 # no cg offset
+        starr[:,3] = 0.0 # no cg offset
+        # radius of gyration
+        starr[:,4] = np.sqrt(I_m/A) #ri_x
+        starr[:,5] = np.sqrt(I_m/A) #ri_y
+        # shear center
+        starr[:,6] = 0.0 # no shear center offset
+        starr[:,7] = 0.0 # no shear center offset
+        # E, G: choose
+        starr[:,8] = mat[:,1]
+        starr[:,9] = mat[:,2]
+        starr[:,10] = I_g
+        starr[:,11] = I_g
+        starr[:,12] = I_g*2
+        # shear factor
+        starr[:,13] = 3/4 # for circular section check it again
+        starr[:,14] = 3/4 # for circular section check it again
+        starr[:,15] = A
+        starr[:,16] = 0.0 # structural pitch
+        starr[:,17] = 0.0
+        starr[:,18] = 0.0
+
+        st = StFile()
+        st.main_data_sets = {1:{1:starr}}
+
+        return c2_arr, st
+
+    def get_hub(self):
+        # Blade root length, in blade root coordinates (with tilt and cone)
+        # see figure 4-1 in Blade User Manual 4.8
+        root = self.get_key('RCON', 'ROOT')[0,0]
+
+        # Hub mass: the mass of the hub, including the spinner and any blade
+        #   root section.
+        # Hub mass centre: the distance from the intersection of the shaft and
+        #   blade axes to the centre of mass of the hub, in a direction measured
+        #   away from the tower.
+        # Moments of inertia: the moment of inertia of the hub mass about the
+        #   shaft axis must be defined.
+        # The inertia about an axis perpendicular to the shaft may also be
+        #   entered with its origin about the hub centre of mass.
+
+        hubmas = self.get_key('RMASS', 'HUBMAS')[0,0]
+        hubine = self.get_key('RMASS', 'HUBINE')[0,0]
+        # FIXME: which axis is this? Would that translate to both xx and yy in H2?
+        hubine2 = self.get_key('RMASS', 'HUBINE2')[0,0]
+
+        # Enter the Spinner diameter. This is the diameter of any spinner or
+        # nose-cone, within which the blades themselves experience no
+        # aerodynamic forces.
+        spind = self.get_key('RCON', 'SPIND')[0,0]
+
+        cmass_hub = {'x':0, 'y':0, 'z':0, 'm':hubmas,
+                     'Ixx':0, 'Iyy':0, 'Izz':hubine}
+
+        return cmass_hub, root
+
+    def get_drivertain(self, len_shaft):
+
+        # TODO: brake
+        # MSTART BRAKE
+
+        # DTRAIN
+        # dtrain = self.get_key('DTRAIN')
+        ginert = self.get_key('DTRAIN', 'GINERT')[0,0] # generator inertia
+        gratio = self.get_key('DTRAIN', 'GRATIO')[0,0]
+        # The additional inertia of the high speed shaft may also be specified
+        # along with the inertia of the gearbox which is referred to the HSS.
+        gbxinert = self.get_key('DTRAIN', 'GBXINERT')[0,0] # gearbox inertia
+        # FIXME: brake position?
+        bpos = self.get_key('DTRAIN', 'BPOS')[0,0]
+        # LSS seems to have a DOF indicator in LSSDOF, and has 6 elements
+        # 4th element is torsion it seems
+        klss = self.get_key('DTRAIN', 'KLSS')[0,3]
+        # FIXME: what does this damping value mean? Simply C in the dyn system
+        # theta_dt_dt*I + C*theta_dt + K*theta = 0 ?
+        dlss = self.get_key('DTRAIN', 'DLSS')[0,3]
+        # HSS only has one DOF
+        khss = self.get_key('DTRAIN', 'KHSS')[0,0]
+        dhss = self.get_key('DTRAIN', 'DHSS')[0,0]
+
+        # Convert torsional stiffness definition into a beam stiffness
+        # that applies for the considered shaft length (c2_def)
+        G = 80e9 # typical steel value
+        Ip = klss*len_shaft/G
+        starr = np.zeros((2,19))
+        starr[:,0] = [0, len_shaft] # st file is always normalised
+        starr[:,1] = 0.5 # very light but not too light
+        starr[:,2] = 0.0 # no cg offset
+        starr[:,3] = 0.0 # no cg offset
+        # radius of gyration: very light but not too light
+        starr[:,4] = 0.001 #ri_x
+        starr[:,5] = 0.001 #ri_y
+        # shear center
+        starr[:,6] = 0.0 # no shear center offset
+        starr[:,7] = 0.0 # no shear center offset
+        # E, G: choose
+        starr[:,8] = 1e18
+        starr[:,9] = G
+        starr[:,10] = Ip/2 # area inertia's
+        starr[:,11] = Ip/2
+        starr[:,12] = Ip
+        # shear factor
+        starr[:,13] = 1000 # stiff in shear
+        starr[:,14] = 1000
+        starr[:,15] = 10 # cross-section area
+        starr[:,16] = 0.0 # structural pitch
+        starr[:,17] = 0.0 # elastic axis
+        starr[:,18] = 0.0
+        st = StFile()
+        st.main_data_sets = {1:{1:starr}}
+
+        # FIXME: INERTIATOCLUTCH??
+        inertiatoclutch = self.get_key('DTRAIN', 'INERTIATOCLUTCH')
+
+        # FIXME: what is the location of these inertia's?
+        # FIXME: what is the mass? It seems the mass is put elsewhere?
+
+        # cmass_gbx = {'Izz':Izz}
+        # cmass_gen = {'x':x, 'y':y, 'z':z, 'm':nacmas,
+        #              'Ixx':Ixx, 'Iyy':Iyy, 'Izz':Izz}
+
+        cmass_lss = {'x':0, 'y':0, 'z':0, 'm':0,'Ixx':0, 'Iyy':0, 'Izz':ginert}
+        # convert HSS inertia to LSS
+        cmass_hss = {'x':0, 'y':0, 'z':0, 'm':0,'Ixx':0, 'Iyy':0,
+                     'Izz':gbxinert*gratio*gratio}
+
+        return cmass_lss, cmass_hss, st
+
+    def get_nacelle(self):
+
+        # also get the nacell concentrated mass
+        nacmas = self.get_key('NMASS', 'NACMAS')[0,0]
+        # includes the nacelle structure and all the machinery within it.
+        # It does not include the rotor blades and hub. If the Direct Drive
+        # (see 4.1) option is selected, the mass of the generator (see 4.2)
+        # is also excluded.
+
+        # position of cg relative to tower top, nacelle mass coord system
+        # based on figure 4-7 of bladed manual 4.8
+        # FIXME: is this correct? z means SS, and at the edge of the nacelle?
+        nmx = self.get_key('NMASS', 'NMX')[0,0] # width?
+        nmy = self.get_key('NMASS', 'NMY')[0,0] # length?
+        nmz = self.get_key('NMASS', 'NMZ')[0,0] # height?
+        iyaw = self.get_key('NMASS', 'IYAW')[0,0]
+        inod = self.get_key('NMASS', 'INOD')[0,0]
+        iroll = self.get_key('NMASS', 'IROLL')[0,0]
+
+        # MSTART NGEOM
+        # NACW	 x.000
+        # NACL	 x.000
+        # NACH	 x.000
+        # NACZ	 0
+        # NACCD	 x.0
+        # NAERO	N
+
+        # height of the nacelle/towertop: the BLADED model does not have to
+        # have consistent shaft length with tilt angle arriving at the rotor
+        # center, so adjust towertop length in HAWC2 accordingly
+
+        # Tower height: from the ground or sea surface to the yaw bearing
+        # (only needed if the tower itself has not been defined)
+        towht = self.get_key('RCON', 'TOWHT')[0,0]
+
+        # Hub height: from the ground to the centre of the rotor
+        # (i.e. the intersection of the blade and shaft axes)
+        height = self.get_key('RCON', 'HEIGHT')[0,0]
+
+        # horizontal distance between rotor center and tower center line
+        ovrhng = self.get_key('RCON', 'OVRHNG')[0,0]
+        tilt = self.get_key('RCON', 'TILT')[0,0]
+
+        # FOR HAWC2, WE HAVE
+        len_shaft = ovrhng / np.cos(tilt)
+        len_towertop = height - towht - len_shaft*np.sin(tilt)
+        assert len_towertop > 0
+        # assert len_towertop + len_shaft*np.sin(tilt) + towht - height == 0
+
+        # concentrated mass in HAWC2
+        # 1  : nodenr
+        # 2-4: x, y, z offset
+        # 5  : mass
+        # 6-8: Ixx, Iyy, Izz
+        # 9-11: Ixy, Ixz, Iyz (optional)
+        # in HAWC2 we would be in the tower top coordinate system, and is
+        # usually the same as the global coordinate system
+        x = nmx
+        y = -nmy # move upwind wrt tower
+        z = -nmz # move upward
+        Ixx = inod
+        Iyy = iroll
+        Izz = iyaw
+
+        cmass_nacelle = {'x':x, 'y':y, 'z':z, 'm':nacmas,
+                         'Ixx':Ixx, 'Iyy':Iyy, 'Izz':Izz}
+
+        return cmass_nacelle, len_shaft, len_towertop
+
+    def get_towershadow_drag(self):
+        # TODO: tower shadow and tower aerodrag
+
+        # MSTART TOWSDW
+        # TSMODEL	x
+        # TDCORR	 x
+        # MAXDEF	 x.x
+        # WIDTH	 x
+        # LREF	 x.x
+
+        return
+
+    def get_control(self):
+
+        # MSTART CONTROL
+
+        # MSTART PCOEFF
+        # TSRMIN	 x
+        # TSRMAX	 x
+        # TSRSTP	 x.x
+        # PITCH	-x.0E-00
+        # PITCH_END	-x.0E-00
+        # PITCH_STEP	 0
+        # OMEGA	 x.654321
+
+        # MSTART IDLING
+
+        # AEROINFO
+
+        # pitch actuator rate limits
+        pitch_actuator = self.xmlroot.PitchActuator
+        if pitch_actuator.SetpointTrajectory.HasRateLimits:
+            # pitch_actuator.SetpointTrajectory.LowerRateLimit
+            # pitch_actuator.SetpointTrajectory.UpperRateLimit
+            print(pitch_actuator.SetpointTrajectory.UpperRateLimit*30/np.pi)
+
+        if pitch_actuator.SetpointTrajectory.HasAccelerationLimits:
+            # pitch_actuator.SetpointTrajectory.LowerAccelerationLimit
+            # pitch_actuator.SetpointTrajectory.UpperAccelerationLimit
+            print(pitch_actuator.SetpointTrajectory.UpperAccelerationLimit*30/np.pi)
+
+        # pitch_actuator.PositionResponse.values() # 1st or 2nd order
+        # pitch_actuator.PositionResponse.Frequency
+        # pitch_actuator.PositionResponse.Damping
+
+        # pitch_actuator.RateResponse.values() # 1st or 2nd order
+        # pitch_actuator.RateResponse.LagTime
+        # pitch_actuator.PositionResponse.Damping
+
+        # and more: bearing friction, etc
+
+        return
+
+    def convert(self, fname_htc):
+
+        fname_prj = os.path.basename(fname_htc).replace('.htc', '')
+
+        # for convenience, we start from an htc template that otherwise has the
+        # right structure, but has only 2 nodes for each body.
+        # assume it is in the same folder as where the HTC will be written to
+        basepath = os.path.dirname(fname_htc)
+        htc = HTCFile(pjoin(basepath, 'template.htc'))
+
+        # prj = self.PRJ_to_HAWC(pjoin(version, fname_prj))
+        # plot_bladed(prj)
+
+        # cone = prj.get_key('RCON', 'CONE')
+        # Lateral offset: the horizontal offset between the shaft and tower axes.
+
+        # Brake
+        # steps = prj.get_key('BRAKE', 'STEPS')
+        # TORQUE = prj.get_key('BRAKE', 'TORQUE')
+        # TIME = prj.get_key('BRAKE', 'TIME')
+
+        # -------------------------------------------------------------------------
+        # BLADES
+        # extract blade geometry, and add to c2_def section in the htc file
+        c2_blade = self.get_blade_c2_def()
+        htc = add_c2_arr_htc(htc, c2_blade, 'blade1')
+
+        # -------------------------------------------------------------------------
+        # NACELLE
+        cmass_nacelle, len_shaft, len_towertop = self.get_nacelle()
+        # set towertop length
+        # nacelle = htc['new_htc_structure'].get_subsection_by_name('towertop')
+        c2_tt = np.zeros((2,4))
+        c2_tt[1,2] = -len_towertop
+        htc = add_c2_arr_htc(htc, c2_tt, 'towertop')
+
+        # -------------------------------------------------------------------------
+        # attach nacelle mass/inertia to towertop, first node (yaw bearing)
+        towertop = htc['new_htc_structure'].get_subsection_by_name('towertop')
+        values = [v for k,v in cmass_nacelle.items()]
+        cmass = towertop.add_line('concentrated_mass', [1] + values)
+        key = cmass.location().split('/')[-1]
+        towertop[key].comments = 'nacelle mass (inc rotating) and inertia (non-rotating)'
+
+        # -------------------------------------------------------------------------
+        # set shaft length
+        c2_s = np.zeros((2,4))
+        c2_s[1,2] = len_shaft
+        htc = add_c2_arr_htc(htc, c2_s, 'shaft')
+
+        # -------------------------------------------------------------------------
+        # generator and gearbox inertia's, shaft torsional flexibility
+        cmass_lss, cmass_hss, st_shaft = self.get_drivertain(len_shaft)
+        st_shaft.save(pjoin(basepath, f'{fname_prj}_shaft.st'))
+
+        shaft = htc['new_htc_structure'].get_subsection_by_name('shaft')
+        # LSS inertia
+        values = [v for k,v in cmass_lss.items()]
+        cmass = shaft.add_line('concentrated_mass', [2] + values)
+        key = cmass.location().split('/')[-1]
+        shaft[key].comments = 'inertia LSS'
+        # Inertia of the HSS is already expressed wrt LSS
+        values = [v for k,v in cmass_hss.items()]
+        cmass = shaft.add_line('concentrated_mass', [2] + values)
+        gratio = self.get_key('DTRAIN', 'GRATIO')[0,0]
+        key = cmass.location().split('/')[-1]
+        shaft[key].comments = f'inertia HSS, expressed in LSS, GBR={gratio}'
+
+        # -------------------------------------------------------------------------
+        # set tilt angle
+        tilt = self.get_key('RCON', 'TILT')[0,0]
+        ori = htc['new_htc_structure'].orientation
+        # tilt is on the 2nd relative block, and set angle on 2nd set of eulerang
+        # check comments of the htc file:
+        # print(ori['relative__2']['mbdy2_eulerang__2'].comments)
+        ori['relative__2']['mbdy2_eulerang__2'].values = [tilt*180/np.pi, 0, 0]
+        ori['relative__2']['mbdy2_eulerang__2'].comments = 'tilt angle'
+
+        # coning angle
+        cone = self.get_key('RCON', 'CONE')[0,0]
+        # coning is on 3, 4 and 5 (all hub orientations)
+        for k in range(3,6):
+            # print(ori[f'relative__{k}']['mbdy2_eulerang__3'].comments)
+            ori[f'relative__{k}']['mbdy2_eulerang__3'].values = [-cone*180/np.pi, 0, 0]
+            ori[f'relative__{k}']['mbdy2_eulerang__3'].comments = 'cone angle'
+
+        # TODO: blade mounting sweep and cone as well??
+
+        # -------------------------------------------------------------------------
+        # HUB mass as concentrated mass on the shaft end
+        # FIXME: make sure we can get the hub root loads including these inertia's
+        cmass_hub, hublen = self.get_hub()
+        values = [v for k,v in cmass_hub.items()]
+        cmass = shaft.add_line('concentrated_mass', [2] + values)
+        key = cmass.location().split('/')[-1]
+        shaft[key].comments = 'Hub inertia and mass'
+
+        # -------------------------------------------------------------------------
+        # hub lenght
+        c2_hub = np.zeros((2,4))
+        c2_hub[1,2] = hublen
+        htc = add_c2_arr_htc(htc, c2_hub, 'hub1')
+
+        # -------------------------------------------------------------------------
+        # TOWER ST FILE and C2_DEF section
+        # WARNING: only includes nodes that are at centerline, side-elements are
+        # ignored
+        # TODO: compare between TGEOM/TMASS and TSTIFF approaches, it seems that
+        # the shear stiffness is not the same, see check_tower()
+        c2_tow, st = self.get_tower_c2_def_st()
+        st.save(pjoin(basepath, f'{fname_prj}_tower.st'))
+        htc = add_c2_arr_htc(htc, c2_tow, 'tower')
+
+        # hub height
+        htc.wind.center_pos0.values = [0, 0, -self.get_key('RCON', 'HEIGHT')[0,0]]
+
+        # -------------------------------------------------------------------------
+        # set all file names correct
+        tower = htc['new_htc_structure'].get_subsection_by_name('tower')
+        tower.timoschenko_input.filename.values[0] = f'data/{fname_prj}_tower.st'
+
+        shaft = htc['new_htc_structure'].get_subsection_by_name('shaft')
+        shaft.timoschenko_input.filename.values[0] = f'data/{fname_prj}_shaft.st'
+
+        blade1 = htc['new_htc_structure'].get_subsection_by_name('blade1')
+        blade1.timoschenko_input.filename.values[0] = f'data/{fname_prj}_blade.st'
+
+        for body_name in ['towertop', 'hub1']:
+            body = htc['new_htc_structure'].get_subsection_by_name(body_name)
+            body.timoschenko_input.filename.values[0] = 'data/template.st'
+
+        htc['aero'].ae_filename.values[0] = f'data/{fname_prj}.ae'
+        htc['aero'].pc_filename.values[0] = f'data/{fname_prj}.pc'
+
+        # -------------------------------------------------------------------------
+        # SAVE HTC FILE
+        htc.save(pjoin(basepath, f'{fname_htc}'))
+
+        # -------------------------------------------------------------------------
+        # other data files
+
+        # Blade st file
+        st = self.get_blade_st()
+        st.save(pjoin(basepath, f'{fname_prj}_blade.st'))
+
+        # extract profile coefficients and save to pc file
+        pc = self.get_pc(setname_filter='cleanVG')
+        pc.save(pjoin(basepath, f'{fname_prj}.pc'))
+
+        # extract aerodynamic layout, and safe to ae file
+        ae = self.get_ae()
+        ae.save(pjoin(basepath, f'{fname_prj}.ae'))
+
+        # # BLADE c2_def
+        # c2_def = htc['new_htc_structure'].get_subsection_by_name('blade1')['c2_def']
+        # # iterate over all nsec lines, but ignore the line that gives the number of points
+        # for i, sec in enumerate(c2_def.keys()[1:]):
+        #     c2_arr[i,:] = c2_def[sec].values[1:]
+
+        # curvedlength = np.zeros(len(c2_arr[:,2]))
+        # for i in range(1,len(c2_arr[:,2])):
+        #     curvedlength[i]=curvedlength[i-1]+np.linalg.norm(c2_arr[i,0:3]-c2_arr[i-1,0:3])
+
+        # c2_arr = np.zeros((len(c2_def.keys())-1,4))
+        # # iterate over all nsec lines, but ignore the line that gives the number of points
+        # for i, sec in enumerate(c2_def.keys()[1:]):
+        #     c2_arr[i,:] = c2_def[sec].values[1:]
diff --git a/wetb/bladed/readprj.py b/wetb/bladed/readprj.py
new file mode 100644
index 0000000000000000000000000000000000000000..4d5291c627de31ca799c34a59fd880616a526285
--- /dev/null
+++ b/wetb/bladed/readprj.py
@@ -0,0 +1,344 @@
+#!/usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+Created on Wed Jun 23 11:07:50 2021
+
+@author: dave
+"""
+
+# from os.path import join as pjoin
+
+import numpy as np
+from lxml import objectify#, etree)
+
+# from matplotlib import pyplot as plt
+# import pandas as pd
+
+# import wetb
+from wetb.prepost import misc
+# from wetb.hawc2 import (HTCFile, AEFile, PCFile, StFile)
+
+
+# TODO: this dictionary utility could go to a dict sub-class in misc?
+def find_next_unique_key(d, key):
+    k = 1
+    while True:
+        k += 1
+        if key + f'__{k}' not in d:
+            key = key + f'__{k}'
+            return key
+
+
+# TODO: this dictionary utility could go to a dict sub-class in misc?
+def add_new_unique_key(key, values, d):
+    """
+    Add key:values to dictionary d. If key already occurs, append __x
+    where x is the number of previous occurances of key(__x).
+
+    Parameters
+    ----------
+    key : str
+        DESCRIPTION.
+    values : list
+        DESCRIPTION.
+    d : dict
+        Dictionary.
+
+    Returns
+    -------
+    key : str
+        DESCRIPTION.
+    d : dict
+        DESCRIPTION.
+
+    """
+    if key in d:
+        key = find_next_unique_key(d, key)
+    d[key] = [values]
+    return key, d
+
+
+class ReadBladedProject:
+
+    def __init__(self, fname):
+
+        with open(fname, encoding='utf-8') as fobj:
+            xml_str = fobj.read().encode('utf-8')
+        self.bd, self.xmlroot = self.parse_bladeddata(xml_str)
+
+        self.set_attr_and_check()
+
+        # some things are just a little different
+        # TMASS has a list of materials and their properties
+        # get rid of the quotes
+        # tmp = [el.replace("'", '') for el in self.bd['TMASS']['MATERIAL'][0]]
+        # self.bd['TMASS']['MATERIAL'] = tmp
+        unique_mat = set(self.get_key('TMASS', 'MATERIAL').flatten().tolist())
+        self.tow_mat_prop = {k:self.get_key('TMASS', k) for k in unique_mat}
+        # material_props = {}
+        # for k in unique_mat:
+        #     material_props[k.replace("'", '')] = self.get_key('TMASS', k)
+
+    def parse_bladeddata(self, xml_str):
+        """
+        The XML field BladedData contains what seems like the main core input
+        data for BLADED, and formatted in some structured way.
+
+        Parameters
+        ----------
+        xml_str : TYPE
+            DESCRIPTION.
+
+        Returns
+        -------
+        bd : TYPE
+            DESCRIPTION.
+        xmlroot : TYPE
+            DESCRIPTION.
+
+        """
+
+        # root = etree.fromstring(xml)
+        # elems = root.getchildren()
+        # bladeddata = elems[1].text
+
+        xmlroot = objectify.fromstring(xml_str)
+
+        # the non-xml formatted BLADED model is situated in a non-xml field
+        # called BladedData
+        bd = {}
+        mstart = None
+        for i, line in enumerate(xmlroot.BladedData.text.split('\n')):
+
+            # TODO: values embedded in double quotes (") can contain entire
+            # MSTART/MEND sub-sections (so embedded sections)
+
+            # split replace tabs with spaces, split on spaces, remove empty
+            linels = misc.remove_items(line.replace('\t', ' ').split(' '), '')
+            # commas can also be separators, in addition to spaces
+            linels2 = []
+            for k in linels:
+                linels2.extend(k.split(','))
+            linels = misc.remove_items(linels2, '')
+
+            # ignore empty lines
+            if len(linels) < 1:
+                continue
+
+            # entries can be numbers if the previous key contains multiple data points
+            try:
+                float(linels[0])
+                el0isnum = True
+            except ValueError:
+                el0isnum = False
+
+            # start of a sub-section that contains (non-unique) keys as well
+            if linels[0].upper().startswith('MSTART'):
+                mtag = linels[-1]
+                mstart = {}
+
+            # at the end of the sub-section add the sub-section to the main dict
+            elif linels[0].upper().startswith('MEND'):
+                # FIXME: implement MSTART sections embedded in double quoted values
+                try:
+                    # if the section key is not unique, make it so by appending __X
+                    if mtag in bd:
+                        mtag = find_next_unique_key(bd, mtag)
+                    bd[mtag] = mstart
+                except UnboundLocalError:
+                    print('warning: ignored embedded mstart/mend section')
+                    print(f'at line: {i+1}')
+                mstart = None
+
+            # if we are under a sub-section
+            elif mstart is not None:
+                # if the line contains a keyword
+                if not el0isnum:
+                    tag, mstart = add_new_unique_key(linels[0], linels[1:], mstart)
+                # line is datapoint that needs to be added to key that occured before
+                else:
+                    mstart[tag].append(linels)
+
+            # add numerical values to key that occured before
+            elif el0isnum:
+                 bd[tag].append(linels)
+
+            else:
+                tag, bd = add_new_unique_key(linels[0], linels[1:], bd)
+
+        return bd, xmlroot
+
+    def get_key(self, key1, key2=False):
+        """
+        Get key from the BladedData CDATA section and format to int32 or
+        float32 numpy arrays if possible withouth precision loss.
+
+        Parameters
+        ----------
+        key1 : str
+            DESCRIPTION.
+        key2 : str, optional
+            DESCRIPTION. The default is False.
+
+
+        Returns
+        -------
+        numpy.array
+            Values from key1/key2 formatted as a numpy array. Converted to
+            numpy.int32, numpy.float32 if possible withouth precision loss,
+            otherwise an object array is returned.
+
+        """
+
+        if key1 not in self.bd:
+            raise KeyError(f'{key1} not found in BLADED file.')
+
+        if key2 is not False:
+            if key2 not in self.bd[key1]:
+                raise KeyError(f'{key2} not found in MSTART {key1} of BLADED file.')
+            data = self.bd[key1][key2]
+        else:
+            data = self.bd[key1]
+
+        # in case we defined a mstart key
+        if isinstance(data, dict):
+            return data
+
+        # i ,j = len(data), len(data[0])
+
+        # FIXME: this is a very expensive way of converting it, but it might
+        # not matter at all since very little model data is actually considered
+        data_arr = np.array(data)
+        try:
+            data_arr = data_arr.astype(np.int32)
+        except ValueError:
+            try:
+                data_arr = data_arr.astype(np.float32)
+            except ValueError:
+                pass
+
+        return data_arr
+
+        # return np.array(data, dtype=np.float32)
+
+        # if isinstance(data[0], list) and len(data[0]) == 1:
+        #     data = float(data[0])
+        # if isinstance(data[0], list) and len(data[0]) > 1:
+        #     data_arr = np.array(data, dtype=np.float32)
+
+    def set_attr_and_check(self):
+        """Check that BGEOMMB, BMASSMB, BSTIFFMB has indeed the same node
+        repated twice every time.
+        """
+
+        # self.bd['BGEOMMB'].keys(), but only those relevant
+        keysg = ['RJ', 'DIST', 'REF_X', 'REF_Y', 'CHORD', 'TWIST', 'CE_X',
+                 'CE_Y', 'BTHICK', 'FOIL', 'MOVING']
+        nbe = self.get_key('BGEOMMB', 'NBE')[0,0]
+
+        # self.bd['BMASSMB'].keys(), but only those relevant
+        keysm = ['CM_X', 'CM_Y', 'MASS', 'SINER', 'RGRATIO', 'BETA_M']
+
+        # self.bd['BSTIFFMB'].keys(), but only those relevant
+        keyss = ['EIFLAP', 'EIEDGE', 'BETA_S', 'GJ', 'CS_X', 'CS_Y', 'GAFLAP',
+                 'GAEDGE']
+
+        mkeys = ['BGEOMMB', 'BMASSMB', 'BSTIFFMB']
+        for mkey, keys in zip(mkeys, [keysg, keysm, keyss]):
+            for key in keys:
+                res = self.get_key(mkey, key)
+                try:
+                    assert np.allclose(res[0,0::2], res[0,1::2])
+                except TypeError:
+                    # allclose doesn't make sense for text arrays
+                    assert np.compare_chararrays(res[0,0::2], res[0,1::2],
+                                                 '==', True).all()
+                assert res.shape[1]==nbe
+                if hasattr(self, key.lower()):
+                    raise UserWarning(key, 'already exists')
+                setattr(self, key.lower(), res[0,0::2])
+
+    def print_xml_tree(self, fname):
+        """For discovery purposes: print full tree + values/text
+
+
+        Parameters
+        ----------
+        fname : TYPE
+            DESCRIPTION.
+
+        Returns
+        -------
+        None.
+
+        """
+
+        # def print_rec(root):
+        #     # if hasattr(root, 'getparent'):
+        #     #     print(root.getparent().tag.title, end='.')
+        #     #     print_rec(root.getparent())
+        #     for el in root.getchildren():
+        #         print(print_rec(el))
+
+        # def print_root_tree(root):
+        #     root.getparent()
+        #     print()
+
+        # tree = etree.fromstring(xml_str)
+        # els = tree.xpath('/')
+        # for el in els:
+        #     print(el)
+
+        # tree = etree.fromstring(xml_str)
+
+        # xmlroot = objectify.fromstring(xml_str)
+        # with open(fname+'.structure', 'w') as f:
+        #     for line in xmlroot.descendantpaths():
+        #         f.write(line + '\n')
+
+        # Recursive XML parsing python using ElementTree
+        # https://stackoverflow.com/q/28194703/3156685
+
+        roottree = self.xmlroot.getroottree()
+        def print_tree_recursive(root):
+            # print(roottree.getpath(root), end=' : ')
+            # print(root.tag.title())
+            f.write(roottree.getpath(root) + ' : ')
+            f.writelines(root.values())
+            if root.text is not None:
+                f.write(' : ' + root.text)
+            f.write('\n')
+            for elem in root.getchildren():
+                print_tree_recursive(elem)
+        with open(fname+'.structure.value', 'w') as f:
+            for el in self.xmlroot.getchildren():
+                if el.tag.title()!='Bladeddata':
+                    print_tree_recursive(el)
+
+    # def get_frequencies(self):
+    #     """
+    #     """
+
+    #     blades = self.xmlroot.NewGUI.Turbine.Blades.FlexibilityModel
+
+    #     blades.Settings.ModesWithDampingDefined
+    #     blades.PartModes # with lots of BladeModeContainer
+    #     blades.WholeBladeModes
+    #     blades.WholeBladeModes.WholeBladeMode
+
+    #     blades.WholeBladeModes.WholeBladeMode.Name
+    #     blades.WholeBladeModes.WholeBladeMode.Frequency
+    #     blades.WholeBladeModes.WholeBladeMode.Damping
+    #     blades.WholeBladeModes.WholeBladeMode.Components
+    #     len(blades.WholeBladeModes.WholeBladeMode.Components.getchildren())
+    #     # 60 elements
+
+    #     for wholeblademode in blades.WholeBladeModes.iterchildren():
+    #         print(wholeblademode.Name)
+    #         print(wholeblademode.Frequency, wholeblademode.Damping)
+
+    #     tower = self.xmlroot.NewGUI.Turbine.SupportStructure.FlexibilityModel
+    #     for towermode in tower.Modes.getchildren():
+    #         print(towermode.Description)
+    #         towermode.Frequency
+    #         towermode.Damping
diff --git a/wetb/bladed/template.htc b/wetb/bladed/template.htc
new file mode 100644
index 0000000000000000000000000000000000000000..3d58aab3345e23bef7a58a94ed8da02e95d0574e
--- /dev/null
+++ b/wetb/bladed/template.htc
@@ -0,0 +1,324 @@
+;
+begin simulation;
+  time_stop    1;
+  solvertype   1 ;    (newmark)
+  on_no_convergence continue ;
+  convergence_limits 1E3 1.0 1E-7 ;
+  logfile case0.log ;
+  begin newmark;
+    deltat    0.02;
+  end newmark;
+end simulation;
+;----------------------------------------------------------------------------------------------------------------------
+begin new_htc_structure;
+;----------------------------------------------------------------------------------------------------------------------
+  begin main_body;
+    name        tower ;
+    type        timoschenko ;
+    nbodies     1 ;
+    node_distribution     c2_def ;
+    damping_posdef   0.0 0.0 0.0 0.0E-00 0.0E-00 0.0E-00;
+     begin timoschenko_input;
+      filename template.st;
+      set 1 1 ;
+    end timoschenko_input;
+    begin c2_def;
+      nsec 2;
+      sec   1   0   0     0.00  0 ;
+      sec   2   0   0  -100.00  0 ;
+     end c2_def ;
+    end main_body;
+;
+  begin main_body;
+    name        towertop ;
+    type        timoschenko ;
+    nbodies     1 ;
+    node_distribution     c2_def ;
+    damping_posdef   0.0 0.0 0.0 0.0E-00 0.0E-00 0.0E-00;
+    begin timoschenko_input;
+      filename template.st;
+      set 1 1 ;
+    end timoschenko_input;
+    begin c2_def;
+      nsec 2;
+      sec 1 0.0 0.0  0.0    0.0 ;
+      sec 2 0.0 0.0 -1.00   0.0 ;
+    end c2_def ;
+  end main_body;
+;
+  begin main_body;
+    name        shaft ;
+    type        timoschenko ;
+    nbodies     1 ;
+    node_distribution     c2_def ;
+    damping_posdef   0.0 0.0 0.0 0.0E-00 0.0E-00 0.0E-00;
+    begin timoschenko_input;
+      filename template.st;
+      set 1 1 ;
+    end timoschenko_input;
+    begin c2_def;
+      nsec 2;
+      sec 1 0.0 0.0 0.0 0.0 ;
+      sec 2 0.0 0.0 1.0 0.0 ;
+    end c2_def ;
+  end main_body;
+;
+  begin main_body;
+    name        hub1 ;
+    type        timoschenko ;
+    nbodies     1 ;
+    node_distribution     c2_def ;
+    damping_posdef   0.0 0.0 0.0 0.0E-00 0.0E-00 0.0E-00;
+    begin timoschenko_input;
+      filename template.st;
+      set 1 1 ;
+    end timoschenko_input;
+    begin c2_def;
+      nsec 2;
+      sec 1 0.0 0.0 0.0 0.0 ;
+      sec 2 0.0 0.0 1.0 0.0 ;
+    end c2_def ;
+  end main_body;
+;
+  begin main_body;
+    name           hub2 ;
+    copy_main_body hub1;
+  end main_body;
+;
+  begin main_body;
+    name           hub3 ;
+    copy_main_body hub1 ;
+  end main_body;
+;
+  begin main_body;
+    name        blade1 ;
+    type        timoschenko ;
+    nbodies     1 ;
+    node_distribution    c2_def;
+    damping_posdef   0.0 0.0 0.0 0.0E-00 0.0E-00 0.0E-00;
+    begin timoschenko_input ;
+      filename template.st;
+      set 1 1 ;
+    end timoschenko_input;
+    begin c2_def;
+        nsec 2;
+        sec 1    0.00000E+00     0.00000E+00    0.00000E+00   0.00000E+00 ;
+        sec 2    0.00000E+00     0.00000E+00    8.00000E+01   0.00000E+00 ;
+     end c2_def ;
+   end main_body;
+;
+  begin main_body;
+    name           blade2 ;
+    copy_main_body blade1;
+  end main_body;
+;
+  begin main_body;
+    name           blade3 ;
+    copy_main_body blade1 ;
+  end main_body;
+;----------------------------------------------------------------------------------------------------------------------
+;
+  begin orientation;
+    begin base;
+      mbdy   tower;
+      inipos        0.0 0.0 0.0 ;
+      body_eulerang 0.0 0.0 0.0;
+    end base;
+    begin relative;
+      mbdy1  tower last;
+      mbdy2  towertop 1;
+      mbdy2_eulerang 0.0 0.0 0.0;
+    end relative;
+    begin relative;
+      mbdy1  towertop last;
+      mbdy2  shaft 1;
+      mbdy2_eulerang 90.0 0.0 0.0;
+      mbdy2_eulerang 0.0 0.0 0.0; [tilt] 0.0 0.0
+      mbdy2_eulerang 0.0 0.0 0.0; 0.0 0.0 [azi]
+      mbdy2_ini_rotvec_d1 0.0 0.0 -1.0 0.0 ; [init_wr];
+    end relative;
+    begin relative;
+      mbdy1  shaft last;
+      mbdy2  hub1 1;
+      mbdy2_eulerang -90.0 0.0 0.0;
+      mbdy2_eulerang 0.0 180.0 0.0;
+      mbdy2_eulerang 2.5 0.0 0.0; [cone] 0.0 0.0
+    end relative;
+    begin relative;
+      mbdy1  shaft last;
+      mbdy2  hub2 1;
+      mbdy2_eulerang -90.0 0.0 0.0;
+      mbdy2_eulerang 0.0 60.0 0.0;
+      mbdy2_eulerang 2.5 0.0 0.0;
+    end relative;
+    begin relative;
+      mbdy1  shaft last;
+      mbdy2  hub3 1;
+      mbdy2_eulerang -90.0 0.0 0.0;
+      mbdy2_eulerang 0.0 -60.0 0.0;
+      mbdy2_eulerang 2.5 0.0 0.0;
+    end relative;
+    begin relative;
+      mbdy1  hub1 last;
+      mbdy2  blade1 1;
+      mbdy2_eulerang 0.0 0.0 0;
+    end relative;
+    begin relative;
+      mbdy1  hub2 last;
+      mbdy2  blade2 1;
+      mbdy2_eulerang 0.0 0.0 0.0;
+    end relative;
+    begin relative;
+      mbdy1  hub3 last;
+      mbdy2  blade3 1;
+      mbdy2_eulerang 0.0 0.0 0.0;
+    end relative;
+   end orientation;
+;----------------------------------------------------------------------------------------------------------------------
+  begin constraint;
+    begin fix0;
+      body tower;
+    end fix0;
+    begin fix1;
+       mbdy1 tower last ;
+       mbdy2 towertop 1;
+    end fix1;
+    begin bearing1;
+      name  shaft_rot;
+      mbdy1 towertop last;
+      mbdy2 shaft 1;
+      bearing_vector 2 0.0 0.0 -1.0; (0=global.1=mbdy1.2=mbdy2)
+    end bearing1;
+;     begin bearing3;
+;       name  shaft_rot;
+;       mbdy1 towertop last;
+;       mbdy2 shaft 1;
+;       bearing_vector 2 0.0 0.0 -1.0; (0=global.1=mbdy1.2=mbdy2)
+;       omegas 0.0 ;
+;    end bearing3;
+    begin fix1;
+       mbdy1 shaft last ;
+       mbdy2 hub1 1;
+    end fix1;
+    begin fix1;
+       mbdy1 shaft last ;
+       mbdy2 hub2 1;
+    end fix1;
+    begin fix1;
+       mbdy1 shaft last ;
+       mbdy2 hub3 1;
+    end fix1;
+    begin bearing2;
+       name pitch1;
+       mbdy1 hub1 last;
+       mbdy2 blade1 1;
+       bearing_vector 2 0.0 0.0 -1.0;
+    end bearing2;
+    begin bearing2;
+       name pitch2;
+       mbdy1 hub2 last;
+       mbdy2 blade2 1;
+       bearing_vector 2 0.0 0.0 -1.0;
+    end bearing2;
+    begin bearing2;
+       name pitch3;
+       mbdy1 hub3 last;
+       mbdy2 blade3 1;
+       bearing_vector 2 0.0 0.0 -1.0;
+    end bearing2;
+  end constraint;
+end new_htc_structure;
+;----------------------------------------------------------------------------------------------------------------------
+begin wind ;
+  density                 1.225 ;
+  wsp                     1;
+  tint                    0.01;
+  horizontal_input        1     ;
+  windfield_rotations     0.0 0.0 0.0 ;    yaw, tilt, rotation
+  center_pos0             0.0 0.0 -119 ; hub heigth
+  shear_format            3 0.2;
+  turb_format             0     ;  0=none, 1=mann,2=flex
+  tower_shadow_method     3     ;  0=none, 1=potential flow, 2=jet
+;  scale_time_start       100;
+;  wind_ramp_factor   0.0 50 0.0 1.0 ;
+;
+  begin tower_shadow_potential_2;
+    tower_mbdy_link tower;
+    nsec  2;
+    radius      0.0  4.15 ;
+    radius     115.63 2.75 ;
+  end tower_shadow_potential_2;
+end wind;
+;
+begin aerodrag ;
+  begin aerodrag_element ;
+    mbdy_name tower;
+    aerodrag_sections uniform 10 ;
+    nsec 2 ;
+    sec   0.0 0.6 1.0 ;  tower bottom
+    sec 100.0 0.6 1.0 ;  tower top
+  end aerodrag_element;
+;
+  begin aerodrag_element ; Nacelle drag side
+    mbdy_name shaft;
+    aerodrag_sections uniform 2 ;
+    nsec 2 ;
+    sec 0.0   0.8 10.0 ;
+    sec 1.00  0.8 10.0 ;
+  end aerodrag_element;
+end aerodrag;
+;
+begin aero ;
+  nblades  3;
+  hub_vec shaft -3 ;
+  link 1 mbdy_c2_def blade1;
+  link 2 mbdy_c2_def blade2;
+  link 3 mbdy_c2_def blade3;
+  ae_filename        template.ae ;
+  pc_filename        template.pc ;
+  induction_method   0 ;     0=none, 1=normal
+  aerocalc_method    1 ;     0=ingen aerodynamic, 1=med aerodynamic
+  aerosections       2;
+  ae_sets            1 1 1;
+  tiploss_method     1 ;     0=none, 1=prandtl
+  dynstall_method    2 ;     0=none, 1=stig øye method,2=mhh method
+end aero ;
+;----------------------------------------------------------------------------------------------------------------------
+begin output;
+  filename case0;
+  time 0 100;
+  data_format gtsdf;
+  buffer 9999;
+;
+  general time;
+  constraint bearing1 shaft_rot 2; angle and angle velocity
+  constraint bearing2 pitch1 5;    angle and angle velocity
+  constraint bearing2 pitch2 5;    angle and angle velocity
+  constraint bearing2 pitch3 5;    angle and angle velocity
+  aero omega ;
+  aero torque;
+  aero power;
+  aero thrust;
+  wind free_wind 1 0.0 0.0 -100;
+  ; Moments:
+  mbdy momentvec tower  1 1  tower # tower base ;
+  mbdy momentvec tower  1 2 tower # tower yaw bearing ;
+  mbdy momentvec shaft  1 1  shaft # main bearing ;
+  mbdy momentvec blade1 1 1 blade1 # blade 1 root ;
+  mbdy momentvec blade2 1 1 blade2 # blade 2 root ;
+  mbdy momentvec blade3 1 1 blade3 # blade 3 root ;
+  mbdy momentvec blade1 1 2 local # blade 1 50% local e coo ;
+  mbdy momentvec blade2 1 2 local # blade 2 50% local e coo ;
+  mbdy momentvec blade3 1 2 local # blade 3 50% local e coo ;
+  ; Displacements and accellerations
+  mbdy state pos tower 1 1.0 global only 1 # Tower top FA displ;
+  mbdy state pos tower 1 1.0 global only 2 # Tower top SS displ;
+  mbdy state acc tower 1 1.0 global only 1 # Tower top FA acc;
+  mbdy state acc tower 1 1.0 global only 2 # Tower top SS acc;
+  mbdy state pos blade1  1 1.0 global # gl blade 1 tip pos ;
+  mbdy state pos blade2  1 1.0 global # gl blade 2 tip pos ;
+  mbdy state pos blade3  1 1.0 global # gl blade 3 tip pos ;
+  mbdy state pos blade1  1 1.0 blade1 # blade 1 tip pos ;
+end output;
+;
+exit;
diff --git a/wetb/bladed/template.st b/wetb/bladed/template.st
new file mode 100644
index 0000000000000000000000000000000000000000..a4105bad9aaeec43c845ca8cb144e622d1fe0842
--- /dev/null
+++ b/wetb/bladed/template.st
@@ -0,0 +1,10 @@
+1  number of sets, Nset
+-----------------
+#1 Nset number 1
+================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
+           r [0]                    m [1]                   x_cg [2]                y_cg [3]                    ri_x [4]                ri_y [5]                x_sh [6]                y_sh [7]                    E [8]                   G [9]                   I_x [10]                 I_y [11]                  K [12]                  k_x [13]                 k_y [14]                  A [15]                 pitch [16]                x_e [17]                 y_e [18]
+================================================================================================================================================================================================================================================================================================================================================================================================================================================================================================
+$1 2 subset number 1
+   0.000000000000000e+00    0.500000000000000e+00    0.000000000000000e+00    0.000000000000000e+00    0.500000000000000e+00    0.500000000000000e+00    0.000000000000000e+00    0.000000000000000e+00    1.000000000000000e+14    1.000000000000000e+13    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    0.000000000000000e+00    0.000000000000000e+00    0.000000000000000e+00
+   1.000000000000000e+00    0.500000000000000e+00    0.000000000000000e+00    0.000000000000000e+00    0.500000000000000e+00    0.500000000000000e+00    0.000000000000000e+00    0.000000000000000e+00    1.000000000000000e+14    1.000000000000000e+13    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    1.000000000000000e+00    0.000000000000000e+00    0.000000000000000e+00    0.000000000000000e+00
+