1596x
001773
18.10.2022

Nástroj pro vytváření zatížení vodními kapsami v C# pomocí webových služeb

API pro RFEM 6, RSTAB 9 a RSECTION je založeno na konceptu webových služeb. Pro dobrý úvod do této oblasti předvedeme v následujícím článku další příklad v C#.

Příkladem je výpočet zatížení vodou na nosník, které se zvětšuje v důsledku průhybu nosníku. Pro větší flexibilitu by měl mít uživatel možnost vybrat si nosník/y. Kromě toho by se neměla měnit další zatížení na střechu, která působí ve stejném zatěžovacím stavu nezávisle na zatížení vodou. Jsou známy a platí následující okrajové podmínky:

  • Hladina vody nad nedeformovaným systémem
  • Spolupůsobící šířka prutu pro plošné zatížení
  • Číslo zatěžovacího stavu, ve kterém má zatížení působit
  • Plošné zatížení vodou na m vodní hladiny (10000 N/m³)
  • Identifikátor pro identifikaci plošných zatížení

V programu se tak vytvoří následující proměnné:


            

double h_water = 0.1;   // výška vody nad nedeformovaným systémem v [m]
double w_ref = 2;       // referenční šířka pro plošné zatížení v [m]
int load_case_no = 1;   // číslo zatěžovacího stavu, ve kterém působí zatížení
string water_accu_comment = "water accumulation";  // identifikační řetězec
double std_magnitude = 10000;   // plošné zatížení na výšku vody v [N/m^3]


Pro implementaci musí program obsahovat následující prvky:

  1. Vyfiltrování příslušných prutů
  2. Smazání zatížení vodou z předchozích průběhů
  3. Vytvoření nových zatížení
  4. Spuštění výpočtu
  5. Určení průhybu
  6. Návrat ke kroku 3 a vytvoření nových zatížení z deformací
  7. Iterování do dosažení mezní hodnoty

Kromě těchto funkcí je vyžadováno propojení s programem a modelem, různé bloky try-catch a další standardní prvky, ale těm se zde nebudeme blíže věnovat. Tyto prvky jsou pak obsaženy ve zdrojovém kódu, který je ke stažení z odkazu pod článkem.

1. Vyfiltrování příslušných prutů

Nejprve se pomocí funkce get_all_selected_objects získají informace o všech vybraných objektech. Získané pole obsahuje prvky typu object_location, které obsahují například typ, číslo a nadřazené "rodičovské" číslo objektu. V následujícím cyklu se vyjmou čísla všech objektů typu E_OBJECT_TYPE_MEMBER (tj. všechna čísla prutů) a uloží se do pole mem_noes_sel.


            

// získání vybraných objektů
object_location[] obj_locs = model.get_all_selected_objects();

// extrahuje pruty
int[] mem_noes_sel = new int[0];
foreach(object_location obj_loc in obj_locs)
{
	if(obj_loc.type == object_types.E_OBJECT_TYPE_MEMBER)
	{
		Array.Resize(ref mem_noes_sel, mem_noes_sel.Length + 1);
		mem_noes_sel[mem_noes_sel.Length-1] = obj_loc.no;
	}
}


2. Smazání zatížení vodou z předchozích průběhů

Pomocí čísel prutů je nyní možné vyfiltrovat příslušná zatížení na pruty ze všech zatížení na pruty. K tomu slouží cyklus přes čísla zatížení na prut. V tomto cyklu se načítají údaje o zatížení na prut, zkontroluje se, zda čísla prutů odpovídají vybraným číslům prutů, a v případě shody se příslušné zatížení na prut smaže:


            

// smaže všechna zatížení water_accu
// získání všech čísel zatížení na prut
int[] mem_load_noes = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_MEMBER_LOAD, load_case_no);

// cyklus všemi zatíženími na pruty zatěžovacího stavu
foreach(int mem_load_no in mem_load_noes)
{
	// získání zatížení na prut
	member_load mem_load = model.get_member_load(mem_load_no, load_case_no);

	if(mem_load.comment == water_accu_comment)
	{
		// cyklus pro pruty zatížení na prut
		for(int i= 0; i < mem_load.members.Length; i++)
		{
			// cyklus pro pruty zatížení na prut
			for (int j = 0; j < mem_noes_sel.Length; j++)
			{
				if(mem_load.members[i] == mem_noes_sel[j])
				{
					// smazání zatížení na prut
					model.delete_object(object_types.E_OBJECT_TYPE_MEMBER_LOAD, mem_load_no, load_case_no);
				}
			}
		}

		
	}

}


Aby nebyla přepsána žádná další zatížení na prut, načte se naposledy použité číslo zatížení na prut:


            

// získání čísla posledního zatížení
int no_offset = model.get_nth_object_number(object_types.E_OBJECT_TYPE_MEMBER_LOAD,0, load_case_no) + 1;


Dalším krokem je vytvoření nových zatížení na pruty, které je již součástí iteračního cyklu do-while. Tento cyklus má následující strukturu:


            

do
{
	// resetování deformace delta
	delta_def = 0;
	
	// aplikace zatížení
	model.begin_modification("Loads");
	
    // vytvoření zatížení na pruty pro každý prut
	...
    
    model.finish_modification();
    ...
    
	// výpočet zatěžovacího stavu
	...


	// získání deformací konců prutů
	...

// kontrolní kritérium
} while (delta_def > 0.0001);


Pro přerušení iterační smyčky byla vybrána změna deformace, která se zjistí při filtrování výsledků. Pokud se všechny deformace liší od deformace v předchozím cyklu o méně než 0,0001 m (tj. 0,1 mm), iterování se přeruší.

3. Vytvoření nových zatížení

Jako typ zatížení se vybere lichoběžníkové zatížení v globálním směru z, které může mít na začátku a na konci prutu různé hodnoty. Je třeba dát pozor, že pro všechny přenášené parametry musí být příslušná proměnná "Specified" nastavena na hodnotu "true". To je nutné proto, aby se nemusely přenášet všechny parametry třídy a aby se tak objem přenášených dat mohl udržovat na nízké úrovni. Hodnota zatížení se spočítá z počáteční výšky "h_water" (byla zadána) a přidané uzlové deformace v tomto bodě. Tato výška v [m] se vynásobí hodnotou "std_magnitude" v [N/m3] a spolupůsobící šířkou v [m], čímž získáme zatížení na linii [N/m]:


            

// vytvoření zatížení na pruty pro každý prut
for (int i = 0; i < mem_noes_sel.Length; ++i)
{
	member_load mem_load = new member_load();
	mem_load.no = no_offset + i;
	mem_load.comment = water_accu_comment;
	mem_load.members = new int[] { mem_noes_sel[i] };

	mem_load.distance_a_is_defined_as_relative = true;
	mem_load.distance_a_is_defined_as_relativeSpecified = true;
	mem_load.distance_a_relative = 0.0;
	mem_load.distance_a_relativeSpecified = true;

	mem_load.distance_b_is_defined_as_relative = true;
	mem_load.distance_b_is_defined_as_relativeSpecified = true;
	mem_load.distance_b_relative = 1.0;
	mem_load.distance_b_relativeSpecified = true;

	mem_load.load_direction = member_load_load_direction.LOAD_DIRECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE;
	mem_load.load_directionSpecified = true;

	mem_load.load_type = member_load_load_type.LOAD_TYPE_FORCE;
	mem_load.load_typeSpecified = true;
	mem_load.load_distribution = member_load_load_distribution.LOAD_DISTRIBUTION_TRAPEZOIDAL;
	mem_load.load_distributionSpecified = true;
	
    mem_load.magnitude_1 = std_magnitude * ((h_water + mem_end_defs[i,0]) * w_ref);
	mem_load.magnitude_1Specified = true;
	mem_load.magnitude_2 = std_magnitude * ((h_water + mem_end_defs[i,1]) * w_ref);
	mem_load.magnitude_2Specified = true;

	model.set_member_load(load_case_no, mem_load);
    
}


Funkce set_member_load slouží k přenosu zatížení. Aby bylo možné přiřadit zatížení, použije se jako komentář řetězec znaků water_accu_comment. V následujících iteracích se již zatížení nevymažou; místo toho se zadáním čísla zatížení při opětovném přenosu přepíšou. Komentář je tedy nutný pouze pro filtrování a mazání zatížení při restartu aplikace. Dále je pro zadání zatížení zvolen relativní vztah, který se však pohybuje v rozmezí 0-100%.

Dalším krokem je spuštění výpočtu. Za tímto účelem se nejprve vytvoří pole s objekty typu calculate_specific_loading. Toto pole obsahuje všechny zatěžovací stavy / kombinace zatížení, které se mají vypočítat. V tomto konkrétním případě se vytvoří pouze jeden prvek typu zatěžovacího stavu se zadaným číslem zatěžovacího stavu load_case_no:


            

// výpočet zatěžovacího stavu
calculate_specific_loading[] csl = new calculate_specific_loading[1];
csl[0] = new calculate_specific_loading();
csl[0].no = load_case_no;
csl[0].type = case_object_types.E_OBJECT_TYPE_LOAD_CASE;

model.calculate_specific(csl, true);


Poté, co máme k dispozici výsledky, je třeba vyfiltrovat globální deformace na začátku a na konci každého prutu. Pomocí funkce get_results_for_members_global_deformations lze získat všechny globální deformace prutu pro daný zatěžovací stav a pro vybrané pruty. Struktura výsledků je stejná jako v příslušné tabulce v programu RFEM 6. Jednou z variant je načtení délek prutů a porovnání polohy x výsledků. Jiná varianta využívá daného popisu (description) a skutečnosti, že extrémy následují za všemi místy x. Tato varianta byla použita a když se v popisu poprvé objeví "Extrémy", použije se předchozí index pro nalezení posledního místa x prutu. Vzhledem k tomu, že první místo na prutu odpovídá prvnímu záznamu, není nutné žádné další filtrování:


            

// získání deformací konců prutů
for (int i = 0; i < mem_noes_sel.Length; ++i)
{
    members_global_deformations_row[] mem_defs_glbl = model.get_results_for_members_global_deformations(case_object_types.E_OBJECT_TYPE_LOAD_CASE, load_case_no, mem_noes_sel[i]);

    // převzetí počátečního bodu
    // výpočet deformace delta
    if (Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl[0].row.displacement_z) > delta_def)
        delta_def = Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl[0].row.displacement_z);

    mem_end_defs[i, 0] = mem_defs_glbl[0].row.displacement_z;
    
    // získání deformace v koncovém bodě
    for (int j = 0; j < mem_defs_glbl.Length; ++j)
    {
        if (mem_defs_glbl[j].description == "Extremes")
        {
            // výpočet deformace delta
            if (Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl[j - 1].row.displacement_z) > delta_def)
                delta_def = Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl[j - 1].row.displacement_z);

            mem_end_defs[i, 1] = mem_defs_glbl[j - 1].row.displacement_z;
            break;
        }
    }
}


Kromě výpočtu deformací se počítá také proměnná "delta_def", která se použije jako kritérium přerušení cyklu. Nejprve se spočítá rozdíl mezi hodnotou deformace z předchozí iterace (nulová na začátku) a aktuální hodnotou. Z rozdílu se vezme absolutní hodnota a pak se hledá maximum. Jak již bylo uvedeno v popisu iteračního cyklu, při hodnotě menší než 0,0001 m (tj. 0,1 mm) je cyklus přerušen.

V přiloženém videu si můžete prohlédnout jednak filtr zatížení a také iterační kroky až do přerušení. Nakonec se zobrazí stanovené zatížení.

Rozhraní Webové služby nabízí nespočet možností pro úpravy prvků v programu RFEM 6 / RSTAB 9, ale také pro načítání výsledků. Lze s ním realizovat mnoho různých projektů. Zde představený program obsahuje první krok pro mnoho různých prvků:

  1. Výběr zvolených prvků
  2. Vytvoření zatížení
  3. Získání a filtrace výsledků
  4. Filtrování prvků podle komentáře
  5. Smazání prvků

Vzhledem k této rozmanitosti může program sloužit také jako šablona pro další projekty.


Autor

Ing. Günthel zajišťuje technickou podporu zákazníkům.

Stahování