Python API II | Concrete-Design results return “Invalid result location” & empty DataFrames

Hi everyone,

I’m trying to read Concrete-Design results from an RFEM 6 model via the new gRPC Python API (dlubal-api v 2.11.1, RFEM 6.11.0001).

  • In the model Concrete Design is enabled and set up for two design situations on one surface.
  • When I open the file in the GUI, in base data, add-ins concrete design is checked
  • After the script runs I can check and there is valid concrete design results there
  • My script calls calculate_all(skip_warnings=True) after opening, so the design is executed in the current session.

Nevertheless every attempt to pull a Concrete-Design table through the API fails with

2025-07-14 22:35:48,983 - WARNING - Could not retrieve concrete design results: <_InactiveRpcError of RPC that terminated with:
        status = StatusCode.UNKNOWN
        details = "Invalid result location."
        debug_error_string = "UNKNOWN:Error received from peer  {grpc_message:"Invalid result location.", grpc_status:2, created_time:"2025-07-14T15:35:48.9539049+00:00"}"
>

and the returned DataFrames are empty:

Concrete Design Ratios By Surface Information:
DataFrame shape: (0, 0)
DataFrame columns: []

Below is the minimal code that reproduces the issue:

import logging
from dlubal.api import rfem

logging.basicConfig(level=logging.INFO, format="%(message)s")
logger = logging.getLogger(__name__)

api_key = "🔑"
model_path = r"..."

with rfem.Application(api_key_value=api_key) as app:
    app.open_model(path=model_path)

    base_data = app.get_base_data()
    # not sure if I have to do this or not as the original model was created in Python 
    # and activate concrete_design add ons there and saved it, now just re-accessing it
    # to test results extractions and save time
    if not base_data.addons.concrete_design_active:
        base_data.addons.concrete_design_active = True


        app.set_base_data(base_data)   
        app.save_model()              

    app.calculate_all(skip_warnings=True)

    try:
        ratios_by_surf  = app.get_results(
            rfem.results.CONCRETE_DESIGN_SURFACES_DESIGN_RATIOS_BY_SURFACE
        ).data
        check_details   = app.get_results(
            rfem.results.CONCRETE_DESIGN_DESIGN_CHECK_DETAILS
        ).data
        ratios_elements = app.get_results(
            rfem.results.CONCRETE_DESIGN_SURFACES_DESIGN_RATIOS
        ).data

        logger.info("\nConcrete Design – Ratios by Surface")
        logger.info(f"shape   : {ratios_by_surf.shape}")
        logger.info(f"columns : {list(ratios_by_surf.columns)}")

    except Exception as e:
        logger.warning(f"Could not retrieve concrete design results: {e!r}")

Environment

Item Version
RFEM 6.11.0001
dlubal-api 2.11.1
Python 3.11.9
OS Windows 10

Also I purchased the Basic Subscription for the API so I have access to Access to all input data and results (ie add ins which from my understanding Free Subscription doesn't allow). That being said I can't see anywhere in my account apart from the paid invoice that specifies I have this tier? Not sure if that could be the issue?

Any ideas what I am doing wrong? I can sent my model file and full script if that helps :)

Any help appreciated—thanks!
Samuel

Hi Samuel,

Thanks for your another interesting question!

Why you're getting Invalid result location

In general, Design Add-on results have special part related to getting details for each design check (like using CONCRETE_DESIGN_DESIGN_CHECK_DETAILS in your case). For that you need to define always for which specific design check you would like to get the details, in other words you need to define a row from the table using design_check_details_id . When you try to query or CONCRETE_DESIGN_DESIGN_CHECK_DETAILS without specifying adesign_check_details_id, RFEM doesn't know which check you're referring to, hence the "Invalid result location" error.

:white_check_mark: Recommended Workflow

If you're after the detailed check results (e.g., the governing check with the highest design ratio), you can follow this pattern:

from dlubal.api import rfem

with rfem.Application() as rfem_app:
    # Get surface design ratios
    concrete_design_checks = rfem_app.get_results(
        results_type=rfem.results.CONCRETE_DESIGN_SURFACES_DESIGN_RATIOS
    ).data

    print("\nConcrete Design Ratios by Surface:")
    print(concrete_design_checks)

    # Find the maximum design ratio and corresponding check details ID
    max_row = concrete_design_checks.loc[concrete_design_checks['design_ratio'].idxmax()]
    details_id = max_row['design_check_details_id']

    # Query detailed check information for this specific design check
    details = rfem_app.get_results(
        results_type=rfem.results.CONCRETE_DESIGN_DESIGN_CHECK_DETAILS,
        filters=[
            rfem.results.ResultsFilter(
                column_id="design_check_details_id",
                filter_expression=str(details_id)
            )
        ]
    ).data

    print("\nDesign Check Details for Max Ratio:")
    print(details)

    # Extract specific symbol if needed (e.g., 'η')
    max_design_ratio = details.loc[details['symbol'] == 'η', 'value_si'].values[0]
    print(f"η = {max_design_ratio } [-]")

:puzzle_piece: Key Points

  • Use CONCRETE_DESIGN_SURFACES_DESIGN_RATIOS to get the list of performed checks.
  • Each check has a design_check_details_id.
  • Use that ID as a filter when requesting CONCRETE_DESIGN_DESIGN_CHECK_DETAILS.
  • Without this filter, the API cannot resolve which check you want, leading to the error you encountered.

Let me know if you'd like me to help review your model file or full script.

Hope this helps!
Tomas

1 Like

Amazing thanks so much that's worked for me now!

I was digging around the CONCRETE_DESIGN_*** in Results, Associated Enums trying to find where the "Provided Reinforcement by Surface" results where but then found that calculated diameter lives in the SurfaceReinforcement type not the results :)
Associated Enums — Dlubal API documentation

SurfaceReinforcement — Dlubal API documentation

My workflow for concrete design results is now as follows:

I run my concrete foundation with auto calculate diameter for the longitudinal reinforcement and shear stirrups (at fixed spacing), get the calculated diameters and the max utilisation for each unique design description (basically representing the table in governing results).

I’ll dump the code for the result extraction below in case any one in the future ever has the same problem as me – should save them a few hours (or maybe less if they are not new to coding like me...)

def test_foundation_results_extraction(model_path: str = TEST_MODEL_PATH) -> Dict[str, Any]:
    """
    Test the foundation results extraction on an existing model.
    """
    rfem_app = None
    try:
        # Initialize RFEM application
        rfem_app = rfem.Application(api_key_value=rfem6_api_key)
        rfem_app.open_model(path=model_path)

        try:
            # 1) Pull all surface‐reinforcement objects
            reinfs = rfem_app.get_object_list([SurfaceReinforcement()])

            # 2) Filter down to #1 and #2
            for sr in reinfs:
                if sr.no in (1, 2):
                    sr_name = getattr(sr, 'name', None)
                    # Check if this is a stirrup reinforcement
                    is_stirrup = False
                    if hasattr(sr, 'reinforcement_type'):
                        stirrup_type = getattr(SurfaceReinforcement, 'REINFORCEMENT_TYPE_STIRRUPS', None)
                        is_stirrup = sr.reinforcement_type == stirrup_type

                    if is_stirrup:
                        # For stirrups, use stirrup_diameter_calculated and stirrup_spacing
                        if hasattr(sr, 'stirrup_diameter_calculated') and sr.stirrup_diameter_calculated and sr.stirrup_diameter_calculated > 0:
                            dia_mm = sr.stirrup_diameter_calculated * 1000
                            dia_note = "(auto-calculated)"
                        else:
                            dia_mm = 'N/A'
                            dia_note = ''
                        if hasattr(sr, 'stirrup_spacing') and sr.stirrup_spacing and sr.stirrup_spacing > 0:
                            spc_mm = sr.stirrup_spacing * 1000
                        else:
                            spc_mm = 'N/A'
                        logger.info(
                            f"SurfaceReinforcement #{sr.no} (name: {sr_name}) [STIRRUPS] on surface(s) {sr.surfaces}:\n"
                            f"  → Diameter = {dia_mm} mm {dia_note}\n"
                            f"  → Spacing = {spc_mm} mm (set value)\n"
                        )
                    else:
                        # For main reinforcement, use rebar_diameter_calculated and rebar_spacing
                        if sr.rebar_diameter_calculated and sr.rebar_diameter_calculated > 0:
                            dia_mm = sr.rebar_diameter_calculated * 1000
                            dia_note = "(auto-calculated)"
                        elif sr.rebar_diameter and sr.rebar_diameter > 0:
                            dia_mm = sr.rebar_diameter * 1000
                            dia_note = "(set value)"
                        else:
                            dia_mm = 'N/A'
                            dia_note = ''
                        if sr.rebar_spacing and sr.rebar_spacing > 0:
                            spc_mm = sr.rebar_spacing * 1000
                        else:
                            spc_mm = 'N/A'
                        logger.info(
                            f"SurfaceReinforcement #{sr.no} (name: {sr_name}) on surface(s) {sr.surfaces}:\n"
                            f"  → Diameter = {dia_mm} mm {dia_note}\n"
                            f"  → Spacing = {spc_mm} mm (set value)\n"
                        )

            # Get surface design ratios
            concrete_design_checks = rfem_app.get_results(
                results_type=rfem.results.CONCRETE_DESIGN_SURFACES_DESIGN_RATIOS
            ).data

            # Group by design_check_description and find the maximum design_ratio for each
            max_ratios_by_description = []
            
            for description in concrete_design_checks['design_check_description'].unique():
                # Filter data for this specific description
                description_data = concrete_design_checks[concrete_design_checks['design_check_description'] == description]
                
                # Find the row with maximum design_ratio for this description
                max_ratio_idx = description_data['design_ratio'].idxmax()
                max_ratio_row = description_data.loc[max_ratio_idx]
                
                # Extract the required columns
                max_ratios_by_description.append({
                    'design_ratio': max_ratio_row['design_ratio'],
                    'design_check_description': max_ratio_row['design_check_description'],
                    'design_situation_no': max_ratio_row['design_situation_no'],
                    'loading': max_ratio_row['loading']
                })
            
            # Create DataFrame and sort by design_ratio (descending)
            summary_df = pd.DataFrame(max_ratios_by_description)
            summary_df = summary_df.sort_values('design_ratio', ascending=False)
            
            # Log the summary table
            logger.info(f"\nConcrete Design Summary - Maximum Ratios by Check Type:")
            logger.info(f"Total unique design checks: {len(summary_df)}")
            logger.info(f"\n{summary_df.to_string(index=False)}")

        except Exception as e:
            logger.error(f"Failed to extract foundation results: {str(e)}", exc_info=True)
            traceback.print_exc()
            return None

    except Exception as e:
        logger.error(f"Error in test_foundation_results_extraction: {str(e)}", exc_info=True)
        return None
    finally:
        # No need to close rfem_app; leave it open as per user request
        pass

Note: I've now updated to filter by design_check_type instead of design_check_description (should be slightly further) and now I split into two tables, one for DETAILING where the design_check_type starts with DM or DC and one for STRENGTH where the design_check_type starts with UL or SE or MA.

I have to do this because I also work for Australian standards so have to do unique hand calcs to check for minimum reinforcement according to our code (detailing), and as long as the strength checks are less than 0.8 I'm satisfied that it will also pass for the Australian code (just because atm there is no concrete design for Australia).

1 Like