Response Spectrum from GeoZone#
|
Running response spectrum analysis with seismic site data from GeoZone Tool:
Keywords:
spectral analysis response spectrum GeoZone Tool seismic peak ground acceleration |
import math
import re
from math import inf
from dlubal.api import rfem, common, geo_zone_tool
# -------------------------------------------------------
# This example demonstrates response spectrum analysis in RFEM
# with seismic site data transferred from GeoZone Tool.
# It defines the same fixed-column model, modal mass import,
# spectral analysis settings, and result retrieval workflow.
# -------------------------------------------------------
# Editable parameters
GEOZONE_ADDRESS = "Munich, Germany"
COUNTRY_CODE = "DE"
TARGET_RETURN_PERIOD_LAYER_NAME = "475 years"
def html_to_plain_text(value: str | None) -> str:
if not value:
return ""
text = value.replace("<sup>", "^").replace("</sup>", "")
text = text.replace("<sub>", "_").replace("</sub>", "")
text = text.replace("·", " ")
text = re.sub(r"<[^>]+>", "", text)
return text.strip()
def get_seismic_input_from_standards(standards):
load_zones = next(
(
group.load_zones
for group in standards.type_groups
if group.name.lower() in ("earthquake", "seismic")
),
None,
)
if not load_zones:
raise ValueError("No seismic/earthquake load-zone group found for selected country.")
preferred_zone = next(
(
z
for z in load_zones
if z.annex.actual and z.standard.name == "EN 1998-1"
),
next(
(
z
for z in load_zones
if z.annex.actual
),
load_zones[0],
)
)
layer = next(
(
l
for l in preferred_zone.annex.layers
if l.name == TARGET_RETURN_PERIOD_LAYER_NAME
),
preferred_zone.annex.layers[0],
)
return preferred_zone.standard.name, preferred_zone.annex.name, layer
def define_structure() -> list:
"""Define a single fixed column (IPE 550)."""
return [
# Material
rfem.structure_core.Material(
no=1,
name='S235',
),
# CrossSection
rfem.structure_core.CrossSection(
no=1,
name='IPE 550',
material=1,
),
# Nodes
rfem.structure_core.Node(
no=1,
coordinate_2=-2,
),
rfem.structure_core.Node(
no=2,
coordinate_2=-2,
coordinate_3=-4,
),
# Line
rfem.structure_core.Line(
no=1,
definition_nodes=[1, 2],
),
# Member
rfem.structure_core.Member(
no=1,
line=1,
cross_section_start=1,
),
# Support
rfem.types_for_nodes.NodalSupport(
no=1,
user_defined_name_enabled=True,
name="Fixed",
nodes=[1],
spring=common.Vector3d(x=inf, y=inf, z=inf),
rotational_restraint=common.Vector3d(x=inf, y=inf, z=inf),
)
]
def define_loading() -> list:
"""Define load cases, static analysis settings, and seismic mass combinations."""
return [
# Load Case | LC1
rfem.loading.LoadCase(
no=1,
name="Static | Self-weight",
static_analysis_settings=1,
),
# Nodal Loads | LC1
rfem.loads.NodalLoad( # Force
no=1,
nodes=[2],
force_magnitude=1000,
load_direction=rfem.loads.NodalLoad.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE_LENGTH,
load_case=1,
),
rfem.loads.NodalLoad( # Mass
no=2,
load_type=rfem.loads.NodalLoad.LOAD_TYPE_MASS,
nodes=[2],
individual_mass_components=True,
mass=common.Vector3d(x=100, y=100, z=100),
mass_moment_of_inertia=common.Vector3d(x=100, y=100, z=100),
load_case=1,
),
# Static Analysis Settings
rfem.loading.StaticAnalysisSettings(
no=1,
analysis_type=rfem.loading.StaticAnalysisSettings.ANALYSIS_TYPE_GEOMETRICALLY_LINEAR,
mass_conversion_enabled=True,
),
rfem.loading.StaticAnalysisSettings(
no=2,
analysis_type=rfem.loading.StaticAnalysisSettings.ANALYSIS_TYPE_SECOND_ORDER_P_DELTA,
mass_conversion_enabled=True,
consider_favorable_effect_due_to_tension_in_members=True,
),
# --- Combinatoric for Seismic Mass ---
# Combination Wizard
rfem.loading.CombinationWizard(
no=1,
generate_combinations=rfem.loading.CombinationWizard.GENERATE_COMBINATIONS_LOAD_COMBINATIONS,
consider_imperfection_case=True,
static_analysis_settings=2,
),
rfem.loading.CombinationWizard(
no=2,
generate_combinations=rfem.loading.CombinationWizard.GENERATE_COMBINATIONS_RESULT_COMBINATIONS,
),
# Design Situations
rfem.loading.DesignSituation(
no=1,
name="Seismic/Mass Combination - psi-E,i",
design_situation_type=rfem.loading.DesignSituation.DesignSituationType.DESIGN_SITUATION_TYPE_SEISMIC_MASS,
combination_wizard=1,
),
rfem.loading.DesignSituation(
no=2,
name="ULS (EQU) - Seismic",
design_situation_type= rfem.loading.DesignSituation.DesignSituationType.DESIGN_SITUATION_TYPE_EQU_SEISMIC,
combination_wizard=2,
),
]
def define_response_spectra() -> list:
"""Define response spectrum input data for this example."""
return [
rfem.dynamic_loads.ResponseSpectrum(
no=1,
definition_type=rfem.dynamic_loads.ResponseSpectrum.DEFINITION_TYPE_ACCORDING_TO_STANDARD,
user_defined_response_spectrum_step_enabled=False,
is_g_factor_mode=False,
),
]
def define_modal_analysis_settings() -> list:
"""Modal analysis settings and the corresponding modal load case."""
return [
# Modal Analysis Settings
rfem.loading.ModalAnalysisSettings(
no=1,
name='User-defined | Modes=10',
user_defined_name_enabled=True,
acting_masses_about_axis_x_enabled=True,
acting_masses_about_axis_y_enabled=True,
acting_masses_about_axis_z_enabled=True,
acting_masses_in_direction_z_enabled=True,
activate_minimum_initial_prestress=False,
solution_method=rfem.loading.ModalAnalysisSettings.SOLUTION_METHOD_LANCZOS,
number_of_modes=10,
minimum_initial_strain=0.00001,
),
# Modal Load Cases
rfem.loading.LoadCase(
no=2,
analysis_type=rfem.loading.LoadCase.ANALYSIS_TYPE_MODAL_ANALYSIS,
name="Modal Analysis ALL 10",
modal_analysis_settings=1,
),
]
def define_spectral_analysis_settings() -> list:
"""Spectral analysis settings (SRSS + Scaled Sum 30%) and the RSA load case."""
return [
# Spectral Analysis Settings
rfem.loading.SpectralAnalysisSettings(
no=1,
user_defined_name_enabled=True,
name='SRSS | Scaled Sum 30.00 %',
assigned_to='LC 3',
combination_rule_for_periodic_responses=rfem.loading.SpectralAnalysisSettings.COMBINATION_RULE_FOR_DIRECTIONAL_COMPONENTS_SRSS,
use_equivalent_linear_combination=False,
combination_rule_for_directional_components=rfem.loading.SpectralAnalysisSettings.COMBINATION_RULE_FOR_DIRECTIONAL_COMPONENTS_SCALED_SUM,
combination_rule_for_directional_components_value=0.3,
),
# Spectral Load Cases
rfem.loading.LoadCase(
no=3,
analysis_type=rfem.loading.LoadCase.ANALYSIS_TYPE_RESPONSE_SPECTRUM_ANALYSIS,
name="RSA Direction X",
spectral_analysis_settings=1,
response_spectrum_is_enabled_in_direction_x=True,
response_spectrum_in_direction_x=1,
response_spectrum_and_equivalent_load_consider_accidental_torsion=True,
response_spectrum_and_equivalent_load_eccentricity_for_y_direction_relative=0.01,
import_modal_analysis_from=2,
response_spectrum_save_results_of_all_selected_modes=True,
),
]
# -------------------------------------------------------
# MAIN SCRIPT
# -------------------------------------------------------
with rfem.Application() as rfem_app:
# Get seismic data from GeoZone Tool
gzt = geo_zone_tool.GeoZoneTool(
token=rfem_app.api_key.value
)
standards = gzt.get_load_zone_standards(
country_code=COUNTRY_CODE,
language=geo_zone_tool.Language.EN,
)
standard_name, annex_name, selected_layer = get_seismic_input_from_standards(standards)
print("GeoZone input (seismic query):")
print(f"Country: {COUNTRY_CODE}")
print(f"Address: {GEOZONE_ADDRESS}")
print(f"Standard: {standard_name}")
print(f"Annex: {annex_name}")
print(f"Layer: {selected_layer.name} (id={selected_layer.id})")
geozone_result = gzt.get_load_zone_characteristics(
address=GEOZONE_ADDRESS,
load_zone_type=geo_zone_tool.LoadZoneType.SEISMIC,
standard=standard_name,
annex=annex_name,
layer_id=selected_layer.id,
language=geo_zone_tool.Language.EN,
)
print("\nGeoZone output (seismic characteristics):")
print(geozone_result)
# Retrieve reference value of peak ground acceleration
ag_r_variable = next(
(
variable
for characteristic in geozone_result.characteristics
for variable in characteristic.zone_characteristics.characteristics
if variable.name == "a_gR"
),
None,
)
if ag_r_variable is None or ag_r_variable.calculated_value is None:
raise ValueError("GeoZone response does not contain required value 'a_gR'.")
ag_r_name = html_to_plain_text(ag_r_variable.name_html) or ag_r_variable.name
ag_r_unit = html_to_plain_text(ag_r_variable.units_html)
ag_r_value = float(ag_r_variable.calculated_value)
print(f"\n{ag_r_variable.description}:")
print(f"{ag_r_name} = {ag_r_value:.3f} {ag_r_unit}")
rfem_app.close_all_models(save_changes=False)
rfem_app.create_model(name="response_spectrum_from_geozone")
# Set global model settings:
base_data: rfem.BaseData = rfem_app.get_base_data()
# Activate add-ons
base_data.addons.modal_analysis_active = True
base_data.addons.response_spectrum_analysis_active = True
base_data.combinations_settings.combination_wizard_active = True
base_data.combinations_settings.result_combinations_active = True
base_data.combinations_settings.result_combinations_parentheses_active = True
base_data.combinations_settings.result_combinations_consider_sub_results = True
# Set standard
base_data.standards.combination_wizard_standard = rfem.BaseData.Standards.COMBINATION_WIZARD_NATIONAL_ANNEX_AND_EDITION_EN_1990_DIN_2012_08_STANDARD
base_data.standards.load_wizard_standard = rfem.BaseData.Standards.LOAD_WIZARD_NATIONAL_ANNEX_AND_EDITION_EN_1991_DIN_2019_04_STANDARD
base_data.standards.dynamic_analysis_standard = rfem.BaseData.Standards.DYNAMIC_ANALYSIS_NATIONAL_ANNEX_AND_EDITION_EN_1998_1_DIN_2023_11_STANDARD
# Transfer GeoZone location to model base data
base_data.location.altitude = float(geozone_result.geo_location.altitude)
base_data.location.latitude = math.radians(float(geozone_result.geo_location.latitude))
base_data.location.longitude = math.radians(float(geozone_result.geo_location.longitude))
base_data.location.town_city = geozone_result.geo_location.city
# Adjust general settings
base_data.general_settings.gravitational_acceleration = 9.81
rfem_app.set_base_data(base_data=base_data)
rfem_app.delete_all_objects()
# Build model structure and loading
rfem_app.create_object_list(
define_structure() +
define_loading()
)
# Define analysis settings
rfem_app.create_object_list(
define_modal_analysis_settings() +
define_spectral_analysis_settings()
)
# Import masses from combinations to modal load cases
rfem_app.generate_combinations()
lc_list = rfem_app.get_object_list(
objs=[rfem.loading.LoadCase()]
)
for lc in lc_list:
if lc.analysis_type is rfem.loading.LoadCase.ANALYSIS_TYPE_MODAL_ANALYSIS:
lc.import_masses_from.no = 1
lc.import_masses_from.object_type = rfem.ObjectType.OBJECT_TYPE_LOAD_COMBINATION
rfem_app.update_object_list(lc_list)
# Create response spectrum by standard
rfem_app.create_object_list(
objs=define_response_spectra()
)
# Modify response spectrum standard parameters by GeoZone Tool data
spectrum_by_standard = rfem_app.get_object(
rfem.dynamic_loads.ResponseSpectrum(no=1)
)
common.set_values_by_key(
tree=spectrum_by_standard.standard_parameters,
key='a_gr',
values=[ag_r_value]
)
rfem_app.update_object(spectrum_by_standard)
# Retrieve results
rfem_app.calculate_all(skip_warnings=True)
results = rfem_app.get_results(
results_type=rfem.results.ResultsType.SPECTRAL_ANALYSIS_MEMBERS_INTERNAL_FORCES
)
print(f"\nSpectral Analysis | Members Internal Forces:\n{results.data}")
using System.Globalization;
using System.Text.RegularExpressions;
using Google.Protobuf;
using GeoZoneTool;
using GeoZoneTool.Models;
using Common = Dlubal.Api.Common;
using Rfem = Dlubal.Api.Rfem;
// -------------------------------------------------------
// This example demonstrates response spectrum analysis in RFEM
// with seismic site data transferred from GeoZone Tool.
// It defines the same fixed-column model, modal mass import,
// spectral analysis settings, and result retrieval workflow.
// -------------------------------------------------------
// Editable parameters
const string GEOZONE_ADDRESS = "Munich, Germany";
const string COUNTRY_CODE = "DE";
const string TARGET_RETURN_PERIOD_LAYER_NAME = "475 years";
static string HtmlToPlainText(string? value)
{
if (string.IsNullOrEmpty(value)) return "";
var text = value.Replace("<sup>", "^").Replace("</sup>", "");
text = text.Replace("<sub>", "_").Replace("</sub>", "");
text = text.Replace("·", " ");
text = Regex.Replace(text, "<[^>]+>", "");
return text.Trim();
}
static (string StandardName, string AnnexName, LoadzoneLayerShortType Layer) GetSeismicInputFromStandards(
LoadzoneStandardsResponseType standards,
string targetReturnPeriodLayerName)
{
var loadZones = standards.TypeGroups
?.FirstOrDefault(group =>
group.Name != null &&
(group.Name.Equals("earthquake", StringComparison.OrdinalIgnoreCase) ||
group.Name.Equals("seismic", StringComparison.OrdinalIgnoreCase)))
?.Loadzones;
if (loadZones == null || loadZones.Count == 0)
{
throw new InvalidOperationException("No seismic/earthquake load-zone group found for selected country.");
}
var preferredZone =
loadZones.FirstOrDefault(z => z.Annex.Actual && z.Standard.Name == "EN 1998-1")
?? loadZones.FirstOrDefault(z => z.Annex.Actual)
?? loadZones[0];
var layer =
preferredZone.Annex.Layers.FirstOrDefault(l => l.Name == targetReturnPeriodLayerName)
?? preferredZone.Annex.Layers[0];
return (preferredZone.Standard.Name, preferredZone.Annex.Name, layer);
}
static List<IMessage> DefineStructure()
{
// Define a single fixed column (IPE 550).
return new List<IMessage>
{
// Material
new Rfem.StructureCore.Material { No = 1, Name = "S235" },
// CrossSection
new Rfem.StructureCore.CrossSection { No = 1, Name = "IPE 550", Material = 1 },
// Nodes
new Rfem.StructureCore.Node { No = 1, Coordinate2 = -2 },
new Rfem.StructureCore.Node { No = 2, Coordinate2 = -2, Coordinate3 = -4 },
// Line
new Rfem.StructureCore.Line { No = 1, DefinitionNodes = { 1, 2 } },
// Member
new Rfem.StructureCore.Member { No = 1, Line = 1, CrossSectionStart = 1 },
// Support
new Rfem.TypesForNodes.NodalSupport
{
No = 1,
UserDefinedNameEnabled = true,
Name = "Fixed",
Nodes = { 1 },
Spring = new Common.Vector3d { X = double.PositiveInfinity, Y = double.PositiveInfinity, Z = double.PositiveInfinity },
RotationalRestraint = new Common.Vector3d { X = double.PositiveInfinity, Y = double.PositiveInfinity, Z = double.PositiveInfinity },
},
};
}
static List<IMessage> DefineLoading()
{
// Define load cases, static analysis settings, and seismic mass combinations.
return new List<IMessage>
{
// Load Case | LC1
new Rfem.Loading.LoadCase { No = 1, Name = "Static | Self-weight", StaticAnalysisSettings = 1 },
// Nodal Loads | LC1
new Rfem.Loads.NodalLoad // Force
{
No = 1,
Nodes = { 2 },
ForceMagnitude = 1000,
LoadDirection = Rfem.Loads.NodalLoad.Types.LoadDirection.GlobalZOrUserDefinedWTrueLength,
LoadCase = 1,
},
new Rfem.Loads.NodalLoad // Mass
{
No = 2,
LoadType = Rfem.Loads.NodalLoad.Types.LoadType.Mass,
Nodes = { 2 },
IndividualMassComponents = true,
Mass = new Common.Vector3d { X = 100, Y = 100, Z = 100 },
MassMomentOfInertia = new Common.Vector3d { X = 100, Y = 100, Z = 100 },
LoadCase = 1,
},
// Static Analysis Settings
new Rfem.Loading.StaticAnalysisSettings
{
No = 1,
AnalysisType = Rfem.Loading.StaticAnalysisSettings.Types.AnalysisType.GeometricallyLinear,
MassConversionEnabled = true,
},
new Rfem.Loading.StaticAnalysisSettings
{
No = 2,
AnalysisType = Rfem.Loading.StaticAnalysisSettings.Types.AnalysisType.SecondOrderPDelta,
MassConversionEnabled = true,
ConsiderFavorableEffectDueToTensionInMembers = true,
},
// --- Combinatoric for Seismic Mass ---
// Combination Wizard
new Rfem.Loading.CombinationWizard
{
No = 1,
GenerateCombinations = Rfem.Loading.CombinationWizard.Types.GenerateCombinations.LoadCombinations,
ConsiderImperfectionCase = true,
StaticAnalysisSettings = 2,
},
new Rfem.Loading.CombinationWizard
{
No = 2,
GenerateCombinations = Rfem.Loading.CombinationWizard.Types.GenerateCombinations.ResultCombinations,
},
// Design Situations
new Rfem.Loading.DesignSituation
{
No = 1,
Name = "Seismic/Mass Combination - psi-E,i",
DesignSituationType = Rfem.Loading.DesignSituation.Types.DesignSituationType.SeismicMass,
CombinationWizard = 1,
},
new Rfem.Loading.DesignSituation
{
No = 2,
Name = "ULS (EQU) - Seismic",
DesignSituationType = Rfem.Loading.DesignSituation.Types.DesignSituationType.EquSeismic,
CombinationWizard = 2,
},
};
}
static List<IMessage> DefineResponseSpectra()
{
// Define response spectrum input data for this example.
return new List<IMessage>
{
new Rfem.DynamicLoads.ResponseSpectrum
{
No = 1,
DefinitionType = Rfem.DynamicLoads.ResponseSpectrum.Types.DefinitionType.AccordingToStandard,
UserDefinedResponseSpectrumStepEnabled = false,
IsGFactorMode = false,
},
};
}
static List<IMessage> DefineModalAnalysisSettings()
{
// Modal analysis settings and the corresponding modal load case.
return new List<IMessage>
{
// Modal Analysis Settings
new Rfem.Loading.ModalAnalysisSettings
{
No = 1,
Name = "User-defined | Modes=10",
UserDefinedNameEnabled = true,
ActingMassesAboutAxisXEnabled = true,
ActingMassesAboutAxisYEnabled = true,
ActingMassesAboutAxisZEnabled = true,
ActingMassesInDirectionZEnabled = true,
ActivateMinimumInitialPrestress = false,
SolutionMethod = Rfem.Loading.ModalAnalysisSettings.Types.SolutionMethod.Lanczos,
NumberOfModes = 10,
MinimumInitialStrain = 0.00001,
},
// Modal Load Cases
new Rfem.Loading.LoadCase
{
No = 2,
AnalysisType = Rfem.Loading.LoadCase.Types.AnalysisType.ModalAnalysis,
Name = "Modal Analysis ALL 10",
ModalAnalysisSettings = 1,
},
};
}
static List<IMessage> DefineSpectralAnalysisSettings()
{
// Spectral analysis settings (SRSS + Scaled Sum 30%) and the RSA load case.
return new List<IMessage>
{
// Spectral Analysis Settings
new Rfem.Loading.SpectralAnalysisSettings
{
No = 1,
UserDefinedNameEnabled = true,
Name = "SRSS | Scaled Sum 30.00 %",
AssignedTo = "LC 3",
CombinationRuleForPeriodicResponses = Rfem.Loading.SpectralAnalysisSettings.Types.CombinationRuleForPeriodicResponses.Srss,
UseEquivalentLinearCombination = false,
CombinationRuleForDirectionalComponents = Rfem.Loading.SpectralAnalysisSettings.Types.CombinationRuleForDirectionalComponents.ScaledSum,
CombinationRuleForDirectionalComponentsValue = 0.3,
},
// Spectral Load Cases
new Rfem.Loading.LoadCase
{
No = 3,
AnalysisType = Rfem.Loading.LoadCase.Types.AnalysisType.ResponseSpectrumAnalysis,
Name = "RSA Direction X",
SpectralAnalysisSettings = 1,
ResponseSpectrumIsEnabledInDirectionX = true,
ResponseSpectrumInDirectionX = 1,
ResponseSpectrumAndEquivalentLoadConsiderAccidentalTorsion = true,
ResponseSpectrumAndEquivalentLoadEccentricityForYDirectionRelative = 0.01,
ImportModalAnalysisFrom = 2,
ResponseSpectrumSaveResultsOfAllSelectedModes = true,
},
};
}
// -------------------------------------------------------
// MAIN SCRIPT
// -------------------------------------------------------
ApplicationRfem? rfemApp = null;
try
{
rfemApp = new ApplicationRfem();
// Get seismic data from GeoZone Tool
var apiKey = new Connection(Connection.GetConfigPath()).ResolveApiKey("", "");
using var gzt = new GeoZone(apiKey);
var standards = await gzt.GetLoadZoneStandardsAsync(new GetLoadZoneStandardsRequest
{
CountryCode = COUNTRY_CODE,
Language = LanguageEnum.En,
});
var (standardName, annexName, selectedLayer) =
GetSeismicInputFromStandards(standards, TARGET_RETURN_PERIOD_LAYER_NAME);
Console.WriteLine("GeoZone input (seismic query):");
Console.WriteLine($"Country: {COUNTRY_CODE}");
Console.WriteLine($"Address: {GEOZONE_ADDRESS}");
Console.WriteLine($"Standard: {standardName}");
Console.WriteLine($"Annex: {annexName}");
Console.WriteLine($"Layer: {selectedLayer.Name} (id={selectedLayer.Id})");
var geozoneResult = await gzt.GetLoadZoneCharacteristicsAsync(new GetZoneCharacteristicsRequest
{
Address = GEOZONE_ADDRESS,
Type = LoadzoneTypeEnum.Earthquake,
Standard = standardName,
Annex = annexName,
LayerId = selectedLayer.Id,
Language = LanguageEnum.En,
});
Console.WriteLine("\nGeoZone output (seismic characteristics):");
if (geozoneResult == null)
{
Console.WriteLine("GeoZone returned no response.");
return;
}
Console.WriteLine(Serializer.Serialize(geozoneResult));
// Retrieve reference value of peak ground acceleration
var agRVariable = geozoneResult.Characteristics
?.SelectMany(characteristic => characteristic.ZoneCharacteristics.Characteristics)
.FirstOrDefault(variable => variable.Name == "a_gR");
if (agRVariable == null || string.IsNullOrEmpty(agRVariable.CalculatedValue))
{
throw new InvalidOperationException("GeoZone response does not contain required value 'a_gR'.");
}
var agRName = HtmlToPlainText(agRVariable.NameHtml);
if (string.IsNullOrEmpty(agRName)) agRName = agRVariable.Name;
var agRUnit = HtmlToPlainText(agRVariable.UnitsHtml);
var agRValue = double.Parse(agRVariable.CalculatedValue, CultureInfo.InvariantCulture);
Console.WriteLine($"\n{agRVariable.Description}:");
Console.WriteLine($"{agRName} = {agRValue:F3} {agRUnit}");
rfemApp.close_all_models(saveChanges: false);
rfemApp.create_model(name: "response_spectrum_from_geozone");
// Set global model settings:
var baseData = rfemApp.get_base_data();
// Activate add-ons
baseData.Addons.ModalAnalysisActive = true;
baseData.Addons.ResponseSpectrumAnalysisActive = true;
baseData.CombinationsSettings.CombinationWizardActive = true;
baseData.CombinationsSettings.ResultCombinationsActive = true;
baseData.CombinationsSettings.ResultCombinationsParenthesesActive = true;
baseData.CombinationsSettings.ResultCombinationsConsiderSubResults = true;
// Set standard
baseData.Standards.CombinationWizardStandard = Rfem.BaseData.Types.Standards.Types.CombinationWizardStandard.CombinationWizardNationalAnnexAndEditionEn1990Din201208Standard;
baseData.Standards.LoadWizardStandard = Rfem.BaseData.Types.Standards.Types.LoadWizardStandard.LoadWizardNationalAnnexAndEditionEn1991Din201904Standard;
baseData.Standards.DynamicAnalysisStandard = Rfem.BaseData.Types.Standards.Types.DynamicAnalysisStandard.DynamicAnalysisNationalAnnexAndEditionEn19981Din202311Standard;
// Transfer GeoZone location to model base data
baseData.Location.Altitude = double.Parse(geozoneResult.GeoLocation.Altitude, CultureInfo.InvariantCulture);
baseData.Location.Latitude = double.Parse(geozoneResult.GeoLocation.Latitude, CultureInfo.InvariantCulture) * Math.PI / 180.0;
baseData.Location.Longitude = double.Parse(geozoneResult.GeoLocation.Longitude, CultureInfo.InvariantCulture) * Math.PI / 180.0;
baseData.Location.TownCity = geozoneResult.GeoLocation.City;
// Adjust general settings
baseData.GeneralSettings.GravitationalAcceleration = 9.81;
rfemApp.set_base_data(baseData: baseData);
rfemApp.delete_all_objects();
// Build model structure and loading
rfemApp.create_object_list(DefineStructure().Concat(DefineLoading()).ToList());
// Define analysis settings
rfemApp.create_object_list(DefineModalAnalysisSettings().Concat(DefineSpectralAnalysisSettings()).ToList());
// Import masses from combinations to modal load cases
rfemApp.generate_combinations();
var loadCases = rfemApp.get_object_list(new List<IMessage> { new Rfem.Loading.LoadCase() });
foreach (var obj in loadCases)
{
if (obj is Rfem.Loading.LoadCase lc && lc.AnalysisType == Rfem.Loading.LoadCase.Types.AnalysisType.ModalAnalysis)
{
lc.ImportMassesFrom = new Rfem.ObjectId { No = 1, ObjectType = Rfem.ObjectType.LoadCombination };
}
}
rfemApp.update_object_list(loadCases);
// Create response spectrum by standard
rfemApp.create_object_list(DefineResponseSpectra());
// Modify response spectrum standard parameters by GeoZone Tool data
var spectrumByStandard = rfemApp.get_object<Rfem.DynamicLoads.ResponseSpectrum>(
new Rfem.DynamicLoads.ResponseSpectrum { No = 1 });
if (spectrumByStandard != null)
{
Common.TreeTable.SetValuesByKey(
tree: spectrumByStandard.StandardParameters,
key: "a_gr",
values: new List<object> { agRValue });
rfemApp.update_object(spectrumByStandard);
}
// Retrieve results
rfemApp.calculate_all(skipWarnings: true);
var results = rfemApp.get_results(resultsType: Rfem.Results.ResultsType.SpectralAnalysisMembersInternalForces);
Console.WriteLine($"\nSpectral Analysis | Members Internal Forces:\n{results.Data}");
}
catch (Exception ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
finally
{
if (rfemApp != null) rfemApp.close_connection();
}