CapeOpenCalculator::CapeOpenCalculator(const MaterialCalculatorSetup* setupInfo)
                  : BaseCalculator(setupInfo)
{
    // Get the property package name from the library name
    string packageName = _libraryName.substr(_libraryName.find(".")+1);

    if (packageName.find("StanMix")     != string::npos ||
        packageName.find("PCP-SAFT")    != string::npos ||
        packageName.find("TPSI")        != string::npos ||
        packageName.find("vThermo")     != string::npos ||
        packageName.find("GasMix")      != string::npos ||
        packageName.find("IF97")        != string::npos ||
        packageName.find("RefProp")     != string::npos)
    {
        warningMessage("CapeOpenCalculator", "Calculation of properties under "
                       "specific phases is not supported by this property "
                       "package. The returned values will be an average over "
                       "the present phases.\n");
    }

    // Get the property package by its name
    LPDISPATCH pack;
    HRESULT hr = ppm->getPropertyPackage(packageName, &pack);
    if (FAILED(hr))
    {
        errorMessage("CapeOpenCalculator", "Unable to load the specified "
                     "property package.\nCAPE-OPEN error:\n\t%s",
                     COUtilities::GetCOErrorAsString(pack, hr).c_str());
        return;
    }

    // The socket handles the property package from here.
    _socket = new CapeOpenSocket_1_0(pack);
    pack->Release();

    // Set the substance on the material object
    CVariant compIds;
    compIds.MakeArray(_numCompounds, VT_BSTR);
    compIds.SetStringAt(0, _bstr_t(setupInfo->compounds));

    for(int i = 0; i < _numCompounds; ++i)
    {
        compIds.SetStringAt(i, _bstr_t(_compounds[i].c_str()));
    }

    // set component ids of material object
    _socket->GetMaterialObject()->setComponentIds(compIds.Value());

    // Get the phase ids in order to determine which constants should be available
    CVariant phaseNames;
    //phaseNames.MakeArray(COPhases1Ph::Count, VT_R8);
    _socket->GetSupportedPhases(phaseNames);

    _socket->GetMaterialObject()->setVaporPhasePossible(false);
    _socket->GetMaterialObject()->setLiquidPhasePossible(false);
    _socket->GetMaterialObject()->setSolidPhasePossible(false);

    std::wstring error;
    if (phaseNames.CheckArray(VT_BSTR, error))
    {
        // Add the packages to the list.
        for (int i = 0; i < phaseNames.GetCount(); ++i)
        {
            BSTR phaseName = phaseNames.GetStringAt(i);

            if(lstrcmpi(phaseName, COPhases1Ph::VAPOR) == 0)
                _socket->GetMaterialObject()->setVaporPhasePossible(true);
            if(lstrcmpi(phaseName, COPhases1Ph::LIQUID) == 0)
                _socket->GetMaterialObject()->setLiquidPhasePossible(true);
            if(lstrcmpi(phaseName, COPhases1Ph::SOLID) == 0)
                _socket->GetMaterialObject()->setSolidPhasePossible(true);
        }
    }

    // set the fluid constants
    this->setSubstanceConstants();
}