CFD Online Logo CFD Online URL
www.cfd-online.com
[Sponsors]
Home > Forums > Software User Forums > OpenFOAM > OpenFOAM Running, Solving & CFD

Cantera .cti to chemkin openFOAM conversion

Register Blogs Community New Posts Updated Threads Search

Like Tree3Likes
  • 1 Post By Krapf
  • 1 Post By Krapf
  • 1 Post By Krapf

Reply
 
LinkBack Thread Tools Search this Thread Display Modes
Old   July 7, 2022, 13:24
Default Cantera .cti to chemkin openFOAM conversion
  #1
Member
 
Join Date: Jun 2020
Posts: 49
Rep Power: 6
Swirl is on a distinguished road
Hello everyone,

I have a chemical mechanism in the Cantera .cti format, which I want to convert either directly into the Openfoam format for transport properties and reactions or into Chemkin format.

I found some tools online, none of which worked so far. Does anyone know how to do this?

Thank you very much in advance!
Swirl is offline   Reply With Quote

Old   December 23, 2022, 16:08
Default
  #2
Member
 
abdo
Join Date: Apr 2018
Posts: 42
Rep Power: 7
khaledhmz is an unknown quantity at this point
Hello bro,
did you solve the problem or not yet?
khaledhmz is offline   Reply With Quote

Old   December 23, 2022, 16:33
Default
  #3
Member
 
Join Date: Jun 2020
Posts: 49
Rep Power: 6
Swirl is on a distinguished road
Not in the way I intended to, sadly. I ended up manually translating the reaction data into openfoam format. Took quite a while, but I couldn't get anything else to work.
Swirl is offline   Reply With Quote

Old   December 24, 2022, 07:04
Default
  #4
Senior Member
 
Join Date: Oct 2017
Posts: 133
Rep Power: 9
Krapf is on a distinguished road
You can use the development (!) version of Cantera to convert it from CTI to YAML (cti2yaml) and then from YAML to CK (yaml2ck). I did it this way myself to be able to use a reaction mechanism in Fluent.
khaledhmz likes this.
Krapf is offline   Reply With Quote

Old   December 24, 2022, 18:56
Default
  #5
Member
 
abdo
Join Date: Apr 2018
Posts: 42
Rep Power: 7
khaledhmz is an unknown quantity at this point
Quote:
Originally Posted by Krapf View Post
You can use the development (!) version of Cantera to convert it from CTI to YAML (cti2yaml) and then from YAML to CK (yaml2ck). I did it this way myself to be able to use a reaction mechanism in Fluent.
Hi Krapf,
Thank you for your comment,
I try what you said before, so I use cti2yaml mymech.cti to convert from .cti to YAML but I didn't find the script that should use to convert from YAML to ck.
you mention (yaml2ck) to do this but I don't find it in the directory path where I install python, even in the internet I don't find the yaml2ck.py.
Could you help me with this?
khaledhmz is offline   Reply With Quote

Old   December 25, 2022, 06:02
Default
  #6
Senior Member
 
Join Date: Oct 2017
Posts: 133
Rep Power: 9
Krapf is on a distinguished road
Did you compile Cantera from source? See: https://cantera.org/install/compilin...#sec-compiling
yaml2ck is not yet included in the stable version.
khaledhmz likes this.
Krapf is offline   Reply With Quote

Old   December 25, 2022, 16:54
Default
  #7
Member
 
abdo
Join Date: Apr 2018
Posts: 42
Rep Power: 7
khaledhmz is an unknown quantity at this point
Quote:
Originally Posted by Krapf View Post
Did you compile Cantera from source? See: https://cantera.org/install/compilin...#sec-compiling
yaml2ck is not yet included in the stable version.
I tried to compile Cantera from source but I got the following error:
Ps: I use wind10.
(base) PS C:\Users\DELL\cantera> scons build
scons: Reading SConscript files ...
SCons 4.4.0 is using the following Python interpreter:
C:\Users\DELL\anaconda3\python.exe (Python 3.9)
Compiling with MSVC version 14.3
Compiling with MSVC toolset 14.3 (default)
Compiling for architecture: amd64
Compiling using the following toolchain(s): ['default']
INFO: Compiling on 'Intel64 Family 6 Model 94 Stepping 3, GenuineIntel'
INFO: Building Cantera from git commit '2ce92eac2'
INFO: Configuration variables read from 'cantera.conf' and command line:

INFO: Adding conda include and library paths: C:\Users\DELL\anaconda3
Checking for C++ header file cmath... yes
Checking for C++ header file fmt/ostream.h... no
INFO: Using private installation of fmt library.
INFO: Found fmt version 6.2.1
Checking for YAML::Node().Mark()... no
INFO: Using private installation of yaml-cpp library.
Checking for C++ header file gtest/gtest.h... yes
Checking for C++ header file gmock/gmock.h... yes
INFO: Using system installation of Googletest
Checking for C++ header file eigen3/Eigen/Dense... no
Checking for C++ header file Eigen/Dense... no
INFO: Using private installation of Eigen.
INFO: Found Eigen version
Checking whether __GLIBCXX__ is declared... no
Checking whether _LIBCPP_VERSION is declared... no
Checking whether __clang__ is declared... no
Checking for C++ library iomp5... no
Checking for C++ library omp... no
Checking for C++ library gomp... no
ERROR: Boost could not be found. Install Boost headers or set 'boost_inc_dir' to point to the boost headers.

I try to install Boost headers but no thing happened.
khaledhmz is offline   Reply With Quote

Old   December 26, 2022, 06:04
Default
  #8
Senior Member
 
Join Date: Oct 2017
Posts: 133
Rep Power: 9
Krapf is on a distinguished road
Quote:
Originally Posted by khaledhmz View Post
I try to install Boost headers but no thing happened.
Did you successfully install Boost and still get the same error message, or did installing Boost not work?
Krapf is offline   Reply With Quote

Old   December 26, 2022, 07:25
Default
  #9
Member
 
abdo
Join Date: Apr 2018
Posts: 42
Rep Power: 7
khaledhmz is an unknown quantity at this point
Quote:
Originally Posted by Krapf View Post
Did you successfully install Boost and still get the same error message, or did installing Boost not work?
I install Boost from the official site (https://www.boost.org/doc/libs/1_62_...d/windows.html) and then I unzip it in C:\ program files, but the same error keeps appearing. Should I install Boost in a specific folder?

Last edited by khaledhmz; December 26, 2022 at 14:13.
khaledhmz is offline   Reply With Quote

Old   December 27, 2022, 16:08
Default
  #10
Senior Member
 
Join Date: Oct 2017
Posts: 133
Rep Power: 9
Krapf is on a distinguished road
Maybe you should try the prebuilt windows binaries: https://sourceforge.net/projects/boo...naries/1.81.0/. Otherwise I am not able to help you with this problem.
khaledhmz likes this.
Krapf is offline   Reply With Quote

Old   January 2, 2023, 05:38
Default
  #11
Member
 
abdo
Join Date: Apr 2018
Posts: 42
Rep Power: 7
khaledhmz is an unknown quantity at this point
Quote:
Originally Posted by Krapf View Post
Maybe you should try the prebuilt windows binaries: https://sourceforge.net/projects/boo...naries/1.81.0/. Otherwise I am not able to help you with this problem.
Thank you very much Krapf and Happy new year 2023
khaledhmz is offline   Reply With Quote

Old   July 5, 2023, 03:27
Default
  #12
New Member
 
LyLy
Join Date: Jan 2019
Posts: 14
Rep Power: 7
harshabose is on a distinguished road
I know this is old post but I found an easier way to get this done.

I found a conversion tool in a Python package called pyMARS Link.
Pretty straightforward, install it and executable are available for file conversion

This one works too. Link

Or you could use this Python code to convert your files:

Code:
import os
from operator import attrgetter
import logging
from textwrap import fill
import numpy as np
import cantera as ct
from cantera import ck2cti

# number of calories in 1000 Joules
CALORIES_CONSTANT = 4184.0

# Conversion from 1 debye to coulomb-meters
DEBEYE_CONVERSION = 3.33564e-30


def build_arrhenius(rate, reaction_order, reaction_type):
    """Builds Arrhenius coefficient string based on reaction type.

    Parameters
    ----------
    rate : cantera.Arrhenius
        Arrhenius-form reaction rate coefficient
    reaction_order : int or float
        Order of reaction (sum of reactant stoichiometric coefficients)
    reaction_type : {cantera.ElementaryReaction, cantera.ThreeBodyReaction, cantera.PlogReaction}
        Type of reaction

    Returns
    -------
    str
        String with Arrhenius coefficients

    """
    if reaction_type in [ct.ElementaryReaction, ct.PlogReaction]:
        pre_exponential_factor = rate.pre_exponential_factor * 1e3**(reaction_order - 1)

    elif reaction_type == ct.ThreeBodyReaction:
        pre_exponential_factor = rate.pre_exponential_factor * 1e3**reaction_order

    elif reaction_type in [ct.FalloffReaction, ct.ChemicallyActivatedReaction]:
        raise ValueError('Function does not support falloff or chemically activated reactions')
    else:
        raise NotImplementedError('Reaction type not supported: ', reaction_type)
    
    arrhenius = [f'{pre_exponential_factor:.4e}', 
                 f'{rate.temperature_exponent:.3f}', 
                 f'{(rate.activation_energy / CALORIES_CONSTANT):.2f}'
                 ]
    return '  '.join(arrhenius)


def build_falloff_arrhenius(rate, reaction_order, reaction_type, pressure_limit):
    """Builds Arrhenius coefficient strings for falloff and chemically-activated reactions.

    Parameters
    ----------
    rate : cantera.Arrhenius
        Arrhenius-form reaction rate coefficient
    reaction_order : int or float
        Order of reaction (sum of reactant stoichiometric coefficients)
    reaction_type : {ct.FalloffReaction, ct.ChemicallyActivatedReaction}
        Type of reaction
    pressure_limit : {'high', 'low'}
        string designating pressure limit
    
    Returns
    -------
    str
        Arrhenius coefficient string

    """
    assert pressure_limit in ['low', 'high'], 'Pressure range needs to be high or low'

    # Each needs more complicated handling due if high- or low-pressure limit
    if reaction_type == ct.FalloffReaction:
        if pressure_limit == 'low':
            pre_exponential_factor = rate.pre_exponential_factor * 1e3**(reaction_order)
        elif pressure_limit == 'high':
            pre_exponential_factor = rate.pre_exponential_factor * 1e3**(reaction_order - 1)

    elif reaction_type == ct.ChemicallyActivatedReaction:
        if pressure_limit == 'low':
            pre_exponential_factor = rate.pre_exponential_factor * 1e3**(reaction_order - 1)
        elif pressure_limit == 'high':
            pre_exponential_factor = rate.pre_exponential_factor * 1e3**(reaction_order - 2)
    else:
        raise ValueError('Reaction type not supported: ', reaction_type)

    arrhenius = [f'{pre_exponential_factor:.4e}', 
                 f'{rate.temperature_exponent:.3f}', 
                 f'{(rate.activation_energy / CALORIES_CONSTANT):.3e}'
                 ]
    return '  '.join(arrhenius)


def build_falloff(parameters, falloff_function):
    """Creates falloff reaction Troe parameter string

    Parameters
    ----------
    parameters : numpy.ndarray
        Array of falloff parameters; length varies based on ``falloff_function``
    falloff_function : {'Troe', 'SRI'}
        Type of falloff function

    Returns
    -------
    falloff_string : str
        String of falloff parameters

    """
    if falloff_function == 'Troe':
        falloff_string = ('TROE / ' +
                          f'{parameters[0]}  {parameters[1]}  '
                          f'{parameters[2]}  {parameters[3]} /\n'
                          )
    elif falloff_function == 'SRI':
        falloff_string = ('SRI / ' + 
                          f'{parameters[0]}  {parameters[1]}  ' +
                          f'{parameters[2]}  {parameters[3]}  {parameters[4]} /\n'
                          )
    else:
        raise NotImplementedError(f'Falloff function not supported: {falloff_function}')

    return falloff_string


def write_thermo_data(species_list, filename='generated_thermo.dat'):
    """Writes thermodynamic data to Chemkin-format file.

    Parameters
    ----------
    species_list : list of cantera.Species
        List of species objects
    filename : str, optional
        Filename for new Chemkin thermodynamic database file

    """
    with open(filename, 'w') as the_file:

        the_file.write('THERMO\n' + 
                       '   300.000  1000.000  5000.000\n'
                       )

        # write data for each species in the Solution object
        for species in species_list:
            
            composition_string = ''.join([f'{s:2}{int(v):>3}' 
                                          for s, v in species.composition.items()
                                          ])

            # first line has species name, space for notes/date, elemental composition,
            # phase, thermodynamic range temperatures (low, high, middle), and a "1"
            # total length should be 80
            species_string = (
                f'{species.name:<18}' + 
                6*' ' + # date/note field
                f'{composition_string:<20}' +
                'G' + # only supports gas phase
                f'{species.thermo.min_temp:10.3f}' +
                f'{species.thermo.max_temp:10.3f}' +
                f'{species.thermo.coeffs[0]:8.2f}' +
                6*' ' + # unused atomic symbols/formula, and blank space
                '1\n'
                )
            
            # second line has first five coefficients of high-temperature range,
            # ending with a "2" in column 79
            species_string += (
                ''.join([f'{c:15.8e}' for c in species.thermo.coeffs[1:6]]) +
                '    ' +
                '2\n'
            )
            
            # third line has the last two coefficients of the high-temperature range,
            # first three coefficients of low-temperature range, and "3"
            species_string += (
                ''.join([f'{c:15.8e}' for c in species.thermo.coeffs[6:8]]) +
                ''.join([f'{c:15.8e}' for c in species.thermo.coeffs[8:11]]) +
                '    ' +
                '3\n'
            )

            # fourth and last line has the last four coefficients of the
            # low-temperature range, and "4"
            
            species_string += (
                ''.join([f'{c:15.8e}' for c in species.thermo.coeffs[11:15]]) +
                19*' ' +
                '4\n'
            )
            
            the_file.write(species_string)

        the_file.write('END\n')


def write_transport_data(species_list, filename='generated_transport.dat'):
    """Writes transport data to Chemkin-format file.

    Parameters
    ----------
    species_list : list of cantera.Species
        List of species objects
    filename : str, optional
        Filename for new Chemkin transport database file

    """
    geometry = {'atom': '0', 'linear': '1', 'nonlinear': '2'}

    with open(filename, 'w') as the_file:

        # write data for each species in the Solution object
        for species in species_list:
            
            # each line contains the species name, integer representing
            # geometry, Lennard-Jones potential well depth in K,
            # Lennard-Jones collision diameter in angstroms,
            # dipole moment in Debye,
            # polarizability in cubic angstroms, and
            # rotational relaxation collision number at 298 K.
            species_string = (
                f'{species.name:<16}' +
                f'{geometry[species.transport.geometry]:>4}' +
                f'{(species.transport.well_depth / ct.boltzmann):>10.3f}' + 
                f'{(species.transport.diameter * 1e10):>10.3f}' + 
                f'{(species.transport.dipole / DEBEYE_CONVERSION):>10.3f}' + 
                f'{(species.transport.polarizability * 1e30):>10.3f}' + 
                f'{species.transport.rotational_relaxation:>10.3f}' + 
                '\n'
            )
            
            the_file.write(species_string)


def write(solution, output_filename='', path='', 
          skip_thermo=False, skip_transport=False
          ):
    """Writes Cantera solution object to Chemkin-format file.

    Parameters
    ----------
    solution : cantera.Solution
        Model to be written
    output_filename : str, optional
        Name of file to be written; if not provided, use ``solution.name``
    path : str, optional
        Path for writing file.
    skip_thermo : bool, optional
        Flag to skip writing thermo data in separate file
    skip_transport : bool, optional
        Flag to skip writing transport data in separate file

    Returns
    -------
    output_file_name : str
        Name of output model file (.inp)

    Examples
    --------
    >>> gas = cantera.Solution('gri30.cti')
    >>> soln2ck.write(gas)
    reduced_gri30.inp

    """
    if output_filename:
        output_filename = os.path.join(path, output_filename)
    else:
        output_filename = os.path.join(path, f'{solution.name}.inp')
    
    if os.path.isfile(output_filename):
        os.remove(output_filename)
    
    with open(output_filename, 'w') as the_file:

        # Write title block to file
        the_file.write(f'!Chemkin file converted from solution object: {solution.name}\n\n')

        # write species and element lists to file
        element_names = '  '.join(solution.element_names)
        the_file.write(
            'ELEMENTS\n' + 
            f'{element_names}\n' +
            'END\n\n'
            )
        species_names = fill(
            '  '.join(solution.species_names), 
            width=60,
            break_long_words=False,
            break_on_hyphens=False
            )
        the_file.write(
            'SPECIES\n' + 
            f'{species_names}\n'
            'END\n\n'
            )

        # Write reactions to file
        the_file.write('REACTIONS\n')

        #write data for each reaction in the Solution Object
        for reaction in solution.reactions():

            reaction_string = f'{reaction.equation:<51}'

            # The Arrhenius parameters that follow the equation string on the main line 
            # depend on the type of reaction.
            if type(reaction) in [ct.ElementaryReaction, ct.ThreeBodyReaction]:
                arrhenius = build_arrhenius(
                    reaction.rate, 
                    sum(reaction.reactants.values()), 
                    type(reaction)
                    )

            elif type(reaction) == ct.FalloffReaction:
                # high-pressure limit is included on the main reaction line
                arrhenius = build_falloff_arrhenius(
                    reaction.high_rate, 
                    sum(reaction.reactants.values()), 
                    ct.FalloffReaction,
                    'high'
                    )

            elif type(reaction) == ct.ChemicallyActivatedReaction:
                # low-pressure limit is included on the main reaction line
                arrhenius = build_falloff_arrhenius(
                    reaction.low_rate, 
                    sum(reaction.reactants.values()), 
                    ct.ChemicallyActivatedReaction,
                    'low'
                    )

            elif type(reaction) == ct.ChebyshevReaction:
                arrhenius = '1.0e0  0.0  0.0'

            elif type(reaction) == ct.PlogReaction:
                arrhenius = build_arrhenius(
                    reaction.rates[0][1],
                    sum(reaction.reactants.values()), 
                    ct.PlogReaction
                    )
            else:
                raise NotImplementedError(f'Unsupported reaction type: {type(reaction)}')

            reaction_string += arrhenius + '\n'
            
            # need to trim and print third-body efficiencies, if present
            if type(reaction) in [ct.ThreeBodyReaction, ct.FalloffReaction, 
                                  ct.ChemicallyActivatedReaction
                                  ]:
                # trims efficiencies list
                reduced_efficiencies = {s:reaction.efficiencies[s] 
                                        for s in reaction.efficiencies
                                        if s in solution.species_names
                                        }
                efficiencies_str = '  '.join([f'{s}/{v}/' for s, v in reduced_efficiencies.items()])
                if efficiencies_str:
                    reaction_string += efficiencies_str + '\n'
            
            # now write any auxiliary information for the reaction
            if type(reaction) == ct.FalloffReaction:
                # for falloff reaction, need to write low-pressure limit Arrhenius expression
                arrhenius = build_falloff_arrhenius(
                    reaction.low_rate, 
                    sum(reaction.reactants.values()), 
                    ct.FalloffReaction,
                    'low'
                    )
                reaction_string += f'LOW / {arrhenius} /\n'

                # need to print additional falloff parameters if present
                if reaction.falloff.parameters.size > 0:
                    falloff_str = build_falloff(reaction.falloff.parameters, reaction.falloff.type)
                    reaction_string += falloff_str

            elif type(reaction) == ct.ChemicallyActivatedReaction:
                # for chemically activated reaction, need to write high-pressure expression
                arrhenius = build_falloff_arrhenius(
                    reaction.low_rate, 
                    sum(reaction.reactants.values()), 
                    ct.ChemicallyActivatedReaction,
                    'high'
                    )
                reaction_string += f'HIGH / {arrhenius} /\n'

                # need to print additional falloff parameters if present
                if reaction.falloff.parameters.size > 0:
                    falloff_str = build_falloff(reaction.falloff.parameters, reaction.falloff.type)
                    reaction_string += falloff_str

            elif type(reaction) == ct.PlogReaction:
                # just need one rate per line
                for rate in reaction.rates:
                    pressure = f'{rate[0] / ct.one_atm}'
                    arrhenius = build_arrhenius(rate[1], 
                                                sum(reaction.reactants.values()), 
                                                ct.PlogReaction
                                                )
                    reaction_string += f'PLOG / {pressure} {arrhenius} /\n'

            elif type(reaction) == ct.ChebyshevReaction:
                reaction_string += (
                    f'TCHEB / {reaction.Tmin}  {reaction.Tmax} /\n' +
                    f'PCHEB / {reaction.Pmin / ct.one_atm}  {reaction.Pmax / ct.one_atm} /\n' +
                    f'CHEB / {reaction.nTemperature}  {reaction.nPressure} /\n'
                    )
                for coeffs in reaction.coeffs:
                    coeffs_row = ' '.join([f'{c:.6e}' for c in coeffs])
                    reaction_string += f'CHEB / {coeffs_row} /\n'

            if reaction.duplicate:
                reaction_string += 'DUPLICATE\n'
                                
            the_file.write(reaction_string)

        the_file.write('END')

    basename = os.path.splitext(output_filename)[0]
    outputs = [output_filename]

    # write thermo data
    if not skip_thermo:
        write_thermo_data(solution.species(), basename + '_thermo.dat')
        outputs.append(basename + '_thermo.dat')

    # TODO: more careful check for presence of transport data?
    if not skip_transport and all(sp.transport for sp in solution.species()):
        write_transport_data(solution.species(), basename + '_transport.dat')
        outputs.append(basename + '_transport.dat')

    return outputs


def convert(model_file, thermo_file=None, transport_file=None, path=''):
    """Function to convert between Cantera and Chemkin model formats.

    Parameters
    ----------
    model_file : str
        Input model file (Cantera .cti or Chemkin)
    thermo_file : str, optional
        Chemkin thermodynamic properties file
    transport_file : str, optional
        Chemkin transport data file
    path : str, optional
        Path for writing file

    Returns
    -------
    str or list
        Path to converted file, or list of files (for Chemkin)

    Example
    -------
    >>> convert('gri30.inp')
    gri30.cti

    >>> convert('gri30.cti')
    [gri30.inp, gri30_thermo.dat, gri30_transport.dat]

    """
    # check whether Chemkin or Cantera model
    basename = os.path.splitext(os.path.basename(model_file))[0]
    extension = os.path.splitext(os.path.basename(model_file))[1]

    # Chemkin files can have multiple extensions, so easier to check if Cantera
    if extension == '.cti':
        # Convert from Cantera to Chemkin format.
        logging.info('Converter detected Cantera input model: ' + model_file)
        logging.info('Converting to Chemkin format.')

        solution = ct.Solution(model_file)
        converted_files = write(solution, basename + '.inp', path=path)
        return converted_files
    else:
        # Convert from Chemkin to Cantera format.
        logging.info('Converter detected Chemkin input model: ' + model_file)
        logging.info('Converting to Cantera format.')

        converted_file = os.path.join(path, basename + '.cti')

        # calls ck2cti based on given files
        args = [f'--input={model_file}']
        if thermo_file:
            args.append(f'--thermo={thermo_file}')
        if transport_file:
            args.append(f'--transport={transport_file}')
        args.append(f'--output={converted_file}')
        
        # generally Chemkin files have issues (redundant species, etc.) that require this argument
        args.append('--permissive')

        ck2cti.main(args)
        return converted_file

convertedFile = convert("/path/to/your/file/your_file.cti")
Above is not my own code, I just took this from the pyMARS source code and modified it. This will allow you to skip any installation of pyMARS. You do need to have Cantera in your python environment though.

Last edited by harshabose; July 5, 2023 at 07:47.
harshabose is offline   Reply With Quote

Old   October 26, 2023, 12:09
Default
  #13
Senior Member
 
Join Date: Oct 2017
Posts: 133
Rep Power: 9
Krapf is on a distinguished road
Quote:
Originally Posted by Krapf View Post
You can use the development (!) version of Cantera to convert it from CTI to YAML (cti2yaml) and then from YAML to CK (yaml2ck). I did it this way myself to be able to use a reaction mechanism in Fluent.
It is no longer necessary to install the development version of Cantera, as yaml2ck is included in version 3.0.0.
Krapf is offline   Reply With Quote

Reply

Tags
cantera, chemkin mechanism


Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
Map of the OpenFOAM Forum - Understanding where to post your questions! wyldckat OpenFOAM 10 September 2, 2021 06:29
[Commercial meshers] Conversion Fluent cas and dat file to OpenFoam matteo_gautero OpenFOAM Meshing & Mesh Conversion 11 July 14, 2020 13:09
OpenFOAM Training: Programming CFD Course 12-13 and 19-20 April 2016 cfd.direct OpenFOAM Announcements from Other Sources 0 January 14, 2016 11:19
OpenFOAM v3.0.1 Training, London, Houston, Berlin, Jan-Mar 2016 cfd.direct OpenFOAM Announcements from Other Sources 0 January 5, 2016 04:18
[Other] Mesh Conversion: OpenFoam (polyMesh format) to Calculix gillers18 OpenFOAM Meshing & Mesh Conversion 2 April 24, 2015 04:37


All times are GMT -4. The time now is 09:43.