1705x
001773
2022-10-18

Ferramenta de serviço web para a formação de bolsas de água em C#

A API para o RFEM 6, o RSTAB 9 e o RSECTION baseia-se no conceito de serviços web. Para obter uma boa introdução ao assunto, o artigo seguinte explica um exemplo adicional em C#.

O exemplo representa o cálculo de uma carga de água numa viga, a qual aumenta com a flecha da viga. Para ser mais flexível, o utilizador deve poder selecionar as vigas. Além do mais, as cargas adicionais que actuam na cobertura, as quais são aplicadas ao mesmo caso de carga independentemente da carga de água, não devem ser modificadas. As seguintes condições de fronteira são conhecidas/aplicadas:

  • Nível da água acima do sistema não deformado
  • Largura da zona de alimentação da barra para carga de superfície
  • Número do caso de carga ao qual a carga será aplicada
  • Carga de superfície de água por m de nível de água (10000 N/m³)
  • Um identificador utilizado para identificar as cargas de superfície

Por isso, são criadas as seguintes variáveis no programa:

  1. code.sharp#

duplo h_água = 0,1; ://altura da água sobre o sistema não deformado em [m]
duplo w_ref = 2; https://www.dlubal.com/pt/largura de referência para carga de superfície em [m]
int load_case_no = 1; ://número do caso de carga onde a carga é aplicada
string Water_accu_comment = "acumulação de água", https://www.dlubal.com/pt
duplo std_magnitude = 10000; ://carga de superfície por altura da água em [N/m^3]

  1. /código#

No que diz respeito à implementação, o programa deve incluir os seguintes elementos:

  1. Filtrar barras seleccionadas
  2. Eliminar cargas de água de execuções anteriores
  3. Criar novas cargas
  4. Iniciar cálculo
  5. A determinar deformação
  6. Voltar ao passo 3 e criar novas cargas a partir das deformações
  7. Repetir iterações até atingir um valor limite

Além dessas funções, são necessárias a ligação ao programa e ao modelo, vários blocos "try-catch" e outros elementos padrão, os quais não são descritos aqui com mais detalhe. Estes elementos serão depois incluídos no código fonte, o qual pode ser descarregado abaixo deste artigo.

1. Filtrar barras selecionadas

Primeiro, obtemos informações sobre todos os objetos selecionados através da função get_all_selected_objects. A matriz recebida contém elementos do tipo localização_objeto, que podem, por exemplo, ser o tipo, o número e o número do objeto "principal" de ordem superior. No ciclo seguinte, os números de todos os objectos do tipo E_OBJECT_TYPE_MEMBER (isto é, todos os números de barra) são extraídos e guardados na matriz mem_noes_sel.

  1. code.csharp#

Object_location[] obj_locs = model.get_all_selected_objects();

https://www.dlubal.com/pt
int[] mem_noes_sel = novo 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;
}
}

  1. /código#

2. Eliminar cargas de água de execuções anteriores

Através de números de barra, agora é possível filtrar as cargas de barra associadas de todas as cargas de barra. É utilizada uma ancoragem colocada sobre os números das cargas de barra. Dentro deste ciclo, obtemos os dados para a carga da barra, verificamos os números das barras quanto à concordância com os números das barras selecionados e, se houver uma correspondência, a carga da barra correspondente será eliminada:

  1. code.csharp#

https://www.dlubal.com/pt/apoio-ao-cliente
https://www.dlubal.com/pt
int[] mem_load_noes = model.get_all_object_numbers(object_types.E_OBJECT_TYPE_MEMBER_LOAD, load_case_no);

https://www.dlubal.com/pt/introductory-videos
foreach(int me_load_no in mem_load_noes)
{
https://www.dlubal.com/pt/carga-de-barra
Member_load mem_load = model.get_member_load(mem_load_no, load_case_no);

if(mem_load.comment == Water_accu_comment)
{
https://www.dlubal.com/pt/barras-de-carga-e-sismos
for(int i= 0; i < mem_load.members.Length; i++)
{
https://www.dlubal.com/pt/barras-de-carga-e-sismos
for (int j = 0; j < mem_noes_sel.Length; j++)
{
if(mem_load.members[i] == mem_noes_sel[j])
{
://eliminar carga de barra
model.delete_object(object_types.E_OBJECT_TYPE_MEMBER_LOAD, mem_load_no, load_case_no);
}
}
}


}

}

  1. /código#

Para que nenhuma outra carga de barra seja substituída, num passo seguinte é lido o último número da carga de barra utilizada:

  1. code.csharp#

https://www.dlubal.com/pt
int no_offset = model.get_nth_object_number(object_types.E_OBJECT_TYPE_MEMBER_LOAD,0, load_case_no) + 1;

  1. /código#

Agora, o próximo passo é criar as novas cargas de barra, o que já faz parte do ciclo de iteração faça enquanto. Este ciclo é construído da seguinte forma:

  1. code.csharp#

do
{
repor a deformação delta
delta_def = 0;


model.begin_modification("Cargas");

  1. /criar cargas de barra para cada barra


  1. model.finish_modification();

https://www.dlubal.com/pt/calcular caso de carga

https://www.dlubal.com/pt/deformações-de-final de barra

https://www.dlubal.com/pt
} enquanto (delta_def > 0.0001);

  1. /código#

Para parar o ciclo de iteração, foi selecionada a alteração da deformação, a qual é determinada ao filtrar os resultados. Se todas as deformações se desviam da deformação anterior em menos de 0,0001 m (isto é, 0,1 mm), o ciclo é interrompido.

3. Criação de novas cargas

É selecionada uma carga trapezoidal a atuar na direção z global, a qual pode ter valores diferentes no início e no final da barra. Tenha em atenção que a variável "especificada" associada tem de ser definida como "verdadeira" para que todos os parâmetros possam ser transferidos. Isto é necessário para não transferir todos os parâmetros de uma classe e para manter a quantidade de dados a ser transferida baixa. O valor da carga's é calculado a partir da altura inicial "h_água" (especificada) e da deformação nodal adicional nesta posição. A altura dada em [m] é multiplicada por "std_magnitude" em [N/m3 ] e a largura da zona de alimentação dada em [m], resultando numa carga de linha dada em [N/m]:

  1. code.csharp#

/criar cargas de barra para cada barra
for (int i = 0; i < mem_noes_sel.Length; ++i)
{
Member_load mem_load = novo Member_load();
mem_load.no = no_offset + i;
mem_load.comment = Water_accu_comment
mem_load.members = novo int[] { mem_noes_sel[i] };

mem_load.istance_a_is_ Defined_as_relative = verdadeiro;
mem_load.istance_a_is_ Defined_as_relativeSpecified = verdadeiro;
mem_load.distance_a_relative = 0,0;
mem_load.distance_a_relativeSpecification = verdadeiro;

mem_load.istance_b_is_ Defined_as_relative = verdadeiro;
mem_load.istance_b_is_ Defined_as_relativeSpecified = verdadeiro;
mem_load.istance_b_relative = 1,0;
mem_load.istance_b_relativeSpecification = verdadeiro;

mem_load.load_direction = Member_load_load_direction.LOAD_DURECTION_GLOBAL_Z_OR_USER_DEFINED_W_TRUE;
mem_load.load_directionSpecification = verdadeiro;

mem_load.load_type = Member_load_load_type.LOAD_TYPE_ForCE;
mem_load.load_typeSpecified = verdadeiro;
mem_load.load_distribution = Member_load_load_distribution.LOAD_Distribution_trapezoidal;
mem_load.load_distributionSpecification = verdadeiro;

  1. mem_load.magnitude_1 = std_magnitude * ((h_água + mem_end_defs[i,0]) * w_ref);

mem_load.magnitude_1especificado = verdadeiro;
mem_load.magnitude_2 = std_magnitude * ((h_água + mem_end_defs[i,1]) * w_ref);
mem_load.magnitude_2Specified = verdadeiro;

model.set_member_load(load_case_no, mem_load);

}

  1. /código#

A função conjunto_member_load é utilizada para transferir a carga. Para a atribuição das cargas, é utilizada a string Water_accu_comment como comentário. Nas iterações seguintes, as cargas não serão mais eliminadas; em vez disso, através da especificação do número da carga, os valores são substituídos quando forem transferidos novamente. Portanto, o comentário apenas é necessário para filtrar e eliminar as cargas quando a aplicação é reiniciada. Além disso, foi escolhida uma referência relativa para a especificação da carga, a qual, contudo, varia de 0-100%.

O próximo passo é iniciar o cálculo. Primeiro, é criado um campo com objetos do tipo calculate_specific_loading. Este campo contém todos os casos/combinações de carga a serem calculados. No presente caso, apenas é criado um elemento do tipo de caso de carga com o número de caso de carga especificado load_case_no:

  1. code.csharp#

https://www.dlubal.com/pt/calcular caso de carga
calculate_specific_loading[] csl = novo calculate_specific_loading[1];
csl[0] = novo calculate_specific_loading();
csl[0].no = load_case_no;
csl[0].type = case_object_types.E_OBJECT_TYPE_LOAD_Case;

model.calculate_specific(csl, verdadeiro);

  1. /código#

Agora que os resultados estão disponíveis, as deformações globais no início e no final de cada barra tem de ser filtradas. A função get_results_for_members_global_deformations é utilizada para obter todas as deformações globais da barra para o caso de carga especificado e as barras selecionadas. A estrutura dos resultados é a mesma que na tabela correspondente no RFEM 6. Uma variante é ler o comprimento da barra e comparar a posição x do resultado. Outra variante utiliza a descrição dada e o facto de que os extremos se seguem após todas as posições x. Foi escolhida a segunda variante e, quando aparece "Extremos" na descrição pela primeira vez, o índice anterior é utilizado para encontrar a última posição x da barra. Uma vez que a primeira posição da barra também afecta a primeira entrada, não é necessária nenhuma filtragem adicional aqui:

  1. code.csharp#

https://www.dlubal.com/pt/deformações-de-final de barra
for (int i = 0; i < mem_noes_sel.Length; ++i)
{

  1. 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]);
  1. https://www.dlubal.com/pt
  2. ://calcular deformação delta
  3. if (Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl[0].row.displacement_z) > delta_def)
  4. delta_def = Math.Abs(mem_end_defs[i, 0] - mem_defs_glbl[0].row.displacement_z);
  1. mem_end_defs[i, 0] = mem_defs_glbl[0].row.displacement_z;
  2. https://www.dlubal.com/pt/deformação no ponto final
  3. for (int j = 0; j < mem_defs_glbl.Length; ++j)
  4. {
  5. if (mem_defs_glbl[j].description == "Extremos")
  6. {
  7. ://calcular deformação delta
  8. if (Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl[j - 1].row.displacement_z) > delta_def)
  9. delta_def = Math.Abs(mem_end_defs[i, 1] - mem_defs_glbl[j - 1].row.displacement_z);
  1. mem_end_defs[i, 1] = mem_defs_glbl[j - 1].row.displacement_z;
  2. rotura;
  3. }
  4. }

}

  1. /código#

Além de determinar as deformações, também é calculada a variável "delta_def", que é utilizada para o critério de paragem. Primeiro, é calculada a diferença entre o valor de deformação da iteração anterior (zero no início) e o valor atual. O valor absoluto é retirado da diferença e depois o máximo é encontrado. Como já apresentado na descrição do ciclo de iteração, paramos num valor inferior a 0.0001 m (ou seja, 0.1 mm).

No vídeo anexado a este artigo, pode ver o filtro de carga por um lado e os passos de iteração até à paragem por outro. No final, é apresentada a carga encontrada.

A interface do serviço web oferece inúmeras opções para a modificação de elementos no RFEM 6/RSTAB 9, mas também para a leitura dos resultados. Muitos projetos diferentes podem ser realizados com ele. O programa apresentado neste artigo inclui apenas um primeiro passo de muitos elementos diferentes:

  1. Obter elementos selecionados
  2. Criar cargas
  3. Obter e filtrar resultados
  4. Filtrar elementos por comentário
  5. Eliminar elementos

Devido a esta variedade, o programa também serve de modelo para outros projetos.


Autor

O Eng. Günthel opera na área do apoio técnico para clientes.

Downloads


;