基于preCICE的Fluent适配器开发分享

1 开发目的

后向台阶流是流动分离现象的经典代表,为了更有效地控制后向台阶流中的重要特征参数,如背部分离压强和湍流强度,进行了耦合分析。通过该耦合分析,能够深入研究后向台阶流的特性,并探索如何控制这些参数对流动的影响。

这项分析基于耦合软件preCICE和FLUENT,在两者之间通过adapter(适配器)的开发建立交互以实现耦合。

2 开发原理

以FLUENT的UDF(user define function)功能对FLUENT进行计算方面的需求拓展,在UDF中调用preCICE中的API(Application Programming interface)实现耦合。

adapter、preCICE、求解器的交互如下图所示:

图片

Fluent UDF 要求

01文件要求

首先关于需要执行的UDF文件,文件拓展名为.c。

其次,UDF必须使用Fluent提供的DEFINE宏进行定义(关于宏的解释在Fluent UDF用户手册)。

需要执行的UDF.c文件必须包含udf.h,即#include "udf.h"

df.h位于的目录X:\安装目录 \ANSYSInc1\v201\fluent\fluent20.1.0\src\udf

02构建要求

通常情况下,如果编写的用户定义函数(UDF)不包含外部库,可以直接通过Fluent GUI界面进行编译,FLUENT将动态地生成所需文件——包含一个Makefile、一个"XXX.udf"文本文件和一个udf_names.c文件。

然而,由于preCICE是外部库,当需要使用preCICE库中的函数时,编译UDF时需要告知Fluent这些外部库函数的存在。而使用Fluent GUI进行编译时无法满足这个需求,因此需要通过命令行编译,同时需要遵循特定的目录结构和文件命名规则,以便让Fluent正确识别和加载UDF。

因此,在开发Fluent adaper的过程中,可以直接使用已有生成的Makefile、XXX.udf和udf_names.c文件,并通过对这些文件进行简单地修改,即可保持现有的文件结构和命名规则,让Fluent能够正确处理和加载UDF。在后文将会详细描述如何进行修改以保证正确编译UDF。

03目录结构

fluent.cas和libudf位于同一个目录下,libudf子目录的内容如下。

若是在linux上构建,则一定有lnamd64,编译后的库(libudf.so)存在于lnamd64的子目录中,子目录的名称取决于模拟是二维/三维、单精度/双精度。

2d:二维单精度模拟

3d:三维单精度模拟

2ddp:二维双精度模拟

3ddp:三维双精度模拟

如果模拟是并行运行,则在lnamd64中存在两个子目录,一个带“_host”后缀、一个带有“_node”后缀,每个子目录都需要存在文件libudf.so的副本。

下面将通过示例说明目录结构形式及各文件的含义。

3D并行单精度为例,对于在3D并行单精度模拟,需要存在以下目录结构:

图片

3D单精度文件结构示例说明

由示例图可知:算例文件与编译的udf库libudf位于同级目录,在libudf中存在子文件lnamd64、src、Makefile。由于该示例为并行,因此lnamd64中存在3d_host和3d_node两个文件夹,若算例修改为串行则将仅存在3d_host。

以下是对各文件的说明:

Step5101642.cas.h5:算例文件

libudf

--lnamd64

----3d_host

------fsi_udf.c:用户编写UDF文件,包含Fluent的DEFINE宏。

------fsi_test.c:用户编写UDF文件,包含使用preCICE代码的自定义C函数。

------fsi_test.h:fsi_test.c的用户编写头文件。

------user.udf:用于定义要编译的文件名(fsi_udf.c、fsi.c和fsi.h)的文本文件,由makefile引用到fsi.c的用户编写头文件中,根据不同需求可能需要编辑此文件。

------udf_names.c:Fluent GUI自动生成的源代码文件;不需要编辑此文件。

------makefile:用于创建正确的编译命令的指令;可能需要编辑此文件以包含正确的目录。

------fsi_udf.o:fsi_udf.c编译的目标文件,即fsi_udf.c编译后得到fsi_udf.o。

------fsi.o:fsi.c编译的目标文件。

------udf_names.o:udf_names.c编译的目标文件。

------libudf.so:Fluent使用的共享库文件。

如何构建Fluent-preCICE adapter

给定上述的 3D、单精度、并行运行的目录结构:

修改 lnamd64/3d_host/user.udf:

将 "CSOURCES=..." 更改为包括要编译的 *.c 源文件的以空格分隔的列表;对于 FSI 情况,应该包括 fsi_udf.c 和 fsi.c。

将 "HSOURCES=..." 更改为包括要编译的 *.h 源文件的以空格分隔的列表;对于 FSI 情况,应该包括 fsi.h。

将 "FLUENT_INC= " 更改为指向 Fluent 安装目录的路径。路径应该是 ./ansys_inc/v195/fluent 这种类型的。

修改 lnamd64/3d_host/makefile:

将 USER_OBJECTS 变量(第 20 行)更改为 libprecice.so 和 Fluent 附带的 Python 库的绝对路径的以空格分隔的列表。

libprecice.so 文件可以在 preCICE 安装位置中找到;例如,install/precice/2.3.0/lib64/libprecice.so。

Python 库可以在 Fluent 安装文件中找到;例如,/opt/Software/ansys/v202/commonfiles/CPython/3_7/linx64/Release/python/lib/libpython3.so。

将 RELEASE 变量更改为 ANSYS 发行版本号;例如,RELEASE=20.2.0。

构建 libudf.so:输入 'make "FLUENT_ARCH=lnamd64"'。

使用 "make clean" 清除构建。

将 lnamd64/3d_host/ 的所有内容复制到 lnamd64/3d_node/。

关于如何调试UDF:https://www.cfd-online.com/Wiki/Udf_debug

配置文件的编写

在上述步骤中完成了构建FLUENT-adapter中关于FLUENT编译要求的文件结构准备,从该步骤开始准备PreCICE的配置文件(.xml)及PreCICE的API调用。

配置文件是求解器与PreCICE交互从而进行耦合的基础,以下为基于PreCIECE使用两个FLUENT进行耦合的配置文件示例:

<?xml version="1.0" encoding="UTF-8" ?>  <precice-configuration>    <log>      <sink        filter="%Severity% > debug and %Rank% = 0"        format="---[precice] %ColorizedSeverity% %Message%"        enabled="true" />    </log>      <solver-interface dimensions="3">      <data:vector name="velocity" />      <data:scalar name="static_pressure" />            <mesh name="FluidOne-Mesh">        <use-data name="velocity" />        <use-data name="static_pressure" />      </mesh>        <mesh name="FluidTwo-Mesh">        <use-data name="velocity" />        <use-data name="static_pressure" />      </mesh>        <participant name="FluidOne">        <use-mesh name="FluidOne-Mesh" provide="yes" />        <use-mesh name="FluidTwo-Mesh" from="FluidTwo" />        <write-data name="velocity" mesh="FluidOne-Mesh" />        <read-data name="static_pressure" mesh="FluidOne-Mesh" />        <mapping:nearest-neighbor           direction="write"          from="FluidOne-Mesh"          to="FluidTwo-Mesh"         constraint="consistent" />        <mapping:nearest-neighbor          direction="read"         from="FluidTwo-Mesh"          to="FluidOne-Mesh"          constraint="consistent" />    </participant>        <participant name="FluidTwo">        <use-mesh name="FluidTwo-Mesh" provide="yes" />        <read-data name="velocity" mesh="FluidTwo-Mesh" />        <write-data name="static_pressure" mesh="FluidTwo-Mesh" />      </participant>        <m2n:sockets from="FluidOne" to="FluidTwo" exchange-directory=".." />        <coupling-scheme:serial-implicit>        <time-window-size value="0.01" valid-digits="6" />        <max-time value="1000" />       <max-iterations value="100" />       <relative-convergence-measure limit="1e-3" data="velocity" mesh="FluidOne-Mesh"/>        <participants first="FluidOne" second="FluidTwo" />       <exchange data="velocity" mesh="FluidTwo-Mesh" from="FluidOne" to="FluidTwo" />       <exchange data="static_pressure" mesh="FluidTwo-Mesh" from="FluidTwo" to="FluidOne" />        <acceleration:constant>      <relaxation value="0.5"/>        </acceleration: constant>     </coupling-scheme:serial-implicit>    </solver-interface>  </precice-configuration>

以下为配置文件中相关标签的解释:

log:定义日志输出的相关信息。

solver-interface:耦合的交界面。

data:vector(scalar) name:耦合交界面上参与耦合的变量名称。

mesh name参与耦合的网格名称。

use-data name:该网格进行耦合的变量。

participant name参与耦合的求解器名称。

use-mesh name:该求解器中参与耦合的网格名称。

write-data name:该求解器写出到preCICE中的耦合变量。

read-data name:该求解器从preCICE中读取的耦合变量。

mapping:nearest-neighbor:该求解器写出数据到preCICE或从preCICE中读取数据的映射方法,上述配置文件中选择nearest-neighbor,可根据需要选择其他的映射方法。

m2n:sockets耦合参与者间的通信模式,上述配置文件中选择sockets,可根据需要选择其他的通信方法。exchange-directory 指定用于在参与者之间交换数据的目录路径。在上述配置文件中,exchange-directory=".." 表示使用当前工作目录的上级目录作为交换目录。

coupling-scheme:定义耦合方案,上述中定义为串行-隐式,并定义了时间窗口大小、耦合仿真的最大时间、每个时间步的最大迭代步数。

relative-convergence-measure:定义相对收敛准则,比较当前残差与时间窗口第一次残差 之间的差异。在上述中,阈值设置为 1e-3,表示残差的相对变化小于或等于 0.001 时被认为是收敛的。

Acceleration加速方法的定义,上述选择的加速方法为constant,可根据需要选择其他的加速方法。

relaxation value:加速方法constant的松弛因子大小,松弛因子是在迭代求解过程中用于调整解的更新速度的参数。它控制了每次迭代中新解与旧解之间的比例关系。通过引入松弛因子,可以平衡求解过程的稳定性和收敛速度。

初始化阶段

初始化的目的主要有:

1. 完全初始化 preCICE 并进行耦合数据设置。

2. 建立与耦合模拟的其他参与者的连接。

3. 对定义的网格进行预处理,并在并行环境中处理分区。

4. 确定可计算的第一个时间步长的最大允许大小。

初始化阶段调用两个PreCICE相关的API:

第一个为precice_createSolverInterface,作用是为耦合参与者构建一个SolverInterce,以便与preCICE建立耦合连接。

图片

参数含义:

  • participantName:参与者的名称,这应该与配置文件中的参与者名称相匹配。

  • configFileName:配置文件的名称,该文件包含了PreCICE的所有配置信息。

  • solverProcessIndex:求解器进程的索引,通常在并行计算中使用。

  • solverProcessSize:求解器进程的总数,通常在并行计算中使用。

第二个为precice_setMeshVertices,作用是在preCICE中构建求解器中关于耦合网格的顶点信息。

图片

参数含义

  • meshID:网格的ID。

  • size:要创建的顶点的数量。

  • positions:一个数组,包含了所有顶点的坐标。数组的长度应该是size乘以空间维度(例如,在3D空间中,长度应该是3*size)。

  • ids:一个数组,用于存储由PreCICE生成的顶点ID。当你调用setMeshVertices函数时,PreCICE会为每个新的顶点生成一个唯一的ID,并将这些ID存储在ids数组中。这样,你就可以在后续的函数调用中引用这些顶点。

图片

adapter初始化阶段的函数调用如下:

  • void coupling_init():对基于PreCICE耦合的求解器进行耦合的初始化。

void coupling_init() {      double solve_dt = 0;    #if !RP_HOST      printf("(%d)entering initialization\n", myid);        int solver_process_id = -1;      int solver_process_size = 0;      int face_size = 0;      double timestep_limit = 0.0;    #if !PARALLEL      solver_process_size = 1;      solver_process_id = 0;  #else      solver_process_size = compute_node_count;      solver_process_id = myid;  #endif        printf("(%d)creating solver interface-------\n", myid);        if (RP_Variable_Exists_P("udf/config-location")) {          const char* config_loc = RP_Get_String("udf/config-location");          printf("(%d)before createSolverinterface,reading udf/config-location\n", myid);          precicec_createSolverInterface(ParName_PreCICE[0], config_loc, solver_process_id,              solver_process_size);      }      else {          Error("Error reading 'udf/config-location' Scheme variable");      }      printf("  (%d) Solver interface created\n", myid);        printf("  (%d) entering count_couplingMesh_FaceSize\n", myid);        face_size = count_couplingMesh_FaceSize();            printf("  (%d) Coupling Mesh have %d face \n", myid,face_size);       set_mesh_position();      printf("(% d) initializing coupled simulation\n", myid);      timestep_limit = precicec_initialize();      solve_dt = fmin(timestep_limit, CURRENT_TIMESTEP);      printf("(% d)CURRENT TIMESTEP=%f\n", myid,solve_dt);        printf("(%d)initialization done\n", myid);    #endif        node_to_host_double_1(solve_dt);/*Fluent自带的宏,能够传递数据*/  #if !RP_NODE      if (RP_Variable_Exists_P("solve/dt")) {          RP_Set_Real("solve/dt", solve_dt);      }      else {          Error("Error reading 'solve/dt' Scheme variable");      }  #endif /* !RP_NODE */    #if !RP_HOST      if (precicec_isActionRequired(precicec_actionWriteIterationCheckpoint())) {          printf("  (%d) Implicit coupling\n", myid);          udf_convergence = 0;          udf_iterate = 1;          precicec_markActionFulfilled(precicec_actionWriteIterationCheckpoint());      }      else {          printf("  (%d) Explicit coupling\n", myid);      }      printf("  (%d) Synchronizing Fluent processes\n", myid);      PRF_GSYNC();        printf("(%d) Leaving INIT\n", myid);  #endif /* !RP_HOST */        node_to_host_int_2(udf_convergence, udf_iterate);    #if !RP_NODE      RP_Set_Integer("udf/convergence", udf_convergence);      RP_Set_Integer("udf/iterate", udf_iterate);  #endif /* !RP_NODE */  
  • Int count_couplingMesh_FaceSize():计算参与耦合的网格上主要面的数量,并赋值给全局变量wet_face_size。

int count_couplingMesh_FaceSize() {        Domain* domain=NULL;      Thread* face_thread=NULL;      face_t face;      domain = Get_Domain(1);      int face_size = 0;        thread_loop_f(face_thread, domain) {          if (Lookup_Thread(domain, CouplingID) == face_thread) {              begin_f_loop(face, face_thread) {                  if (PRINCIPAL_FACE(face, face_thread)) {                      face_size++;                  }                  }end_f_loop(face,face_thread)          }      }      wet_face_size = face_size;        return wet_face_size;  }
  • void set_mesh_position();将耦合面上每个网格的质心坐标存入PreCICE中。

void set_mesh_position() {        printf("  (%d) entering set_mesh_postion() \n", myid);            Domain* domain = NULL;      Thread* face_thread = NULL;        face_t face;        double pos[ND_ND];        int dim = 0;        int face_index = 0;        int faceMeshID = precicec_getMeshID(meshName_preCICE[0]);  /*通过PreCICE给网格名绑定一个ID*/        printf("in set_mesh_position(),faceMeshID is ......%d\n", faceMeshID);        domain = Get_Domain(1);        if (domain = =NULL) {          printf("Error: domain==NULL\n");          exit(1);      }        /*face_coords用来存储每个网格的三维质心坐标*/      face_coords = (double*)malloc(wet_face_size * ND_ND * sizeof(double);        thread_loop_f(face_thread, domain)       {          if (Lookup_Thread(domain, CouplingID) == face_thread) {              begin_f_loop(face, face_thread)               {                  if (PRINCIPAL_FACE_P(face_thread, thread)) {                      F_CENTROID(pos, face, face_thread);                      for (dim = 0, dim < ND_ND, dim++) {                          face_coords[face_index * ND_ND + dim] = pos[dim];                      }                      face_index++;                  }              }end_f_loop(face,face_thread)          }      }        face_indices = (int*)malloc(werface_size * sizeof(int));        precicec_setMeshVertices(faceMeshID, wet_face_size,face_coords, face_indices);        printf("(%d)leaving set_mesh_position\n", myid);    }  

数据交换

在数据交换部分,求解器与PreCICE交互的关键函数为Block的相关函数,若求解器需要写出到preCICE的变量为矢量,则使用writeBlockVectorData。若为标量,则使用WriteBlockScalarVector,若求解器需要读取preCICE中的变量,则使用函数readBlockVectorData或函数readBlockScalarData。

以下为writeBlockVectorData函数的具体说明,其余三个Block的相关函数参数与该函数一致,因此不作赘述。

图片

Parameters:

  • int  dataID, 要读取或者写出数据的ID,preCICE中每个数据集都有一个唯一的dataID,通过dataID可以引用或操作特定的数据集。

  • int  size, 顶点的数量,若为面心网格,则可以理解为面心的质量。

  • const int* valueindices, 顶点的索引。

  • const double* values,保存数据实际值的指针。

假设有两个求解器,求解A和求解B,若求解器A使用WriteBlockVectorData写出了数据,并且在该API中给定了dataID,那么求解B可以通过相同的使用ReadBlockVectorData来读取该数据。

以上为adapter开发中数据交换的基本原理,在实际开发的Fluent adapter中,数据交换阶段的函数调用顺序如下:

图片

通过DEFINE_PROFILE将从PreCICE读取到的变量数值通过映射的方式赋值给耦合网格,通过DEFINE_ON_DEMAND每次写出变量数值到PreCICE中后进行下一个时间步的推进。

下方为求解器1将变量velocity写出到PreCICE中的代码示例:

void Advance_Coupling() {   #if !RP_HOST      if (!is_coupling_going) {          return;      }      if (precicec_isCouplingOngoing() == 0) {          is_coupling_going = preicec_isCouplingOngoing();            precicec_finalize();          return;      }        int subCycling = !precicec_isWriteDataRequired(CURRENT_TIMESTEP);        if (subCycling) {          printf("(%d)In advance_Coupling(),In subscyling,skipping writing.\n", myid);      }        printf("(% d)writing veloity.....\n", myid);        int MeshID = precicec_getMeshID(meshName_PreCICE[0]);        int dataID_preCICE = precicec_getDataID(dataType_PreCICE[0], MeshID);        int data_size = wet_face_size;        Write_velocity(dataID_preCICE, data_size);          printf("(% d)writing veloity done.....\n", myid);      if (precicec_isActionRequired(precicec_actionWriteIterationCheckpoint())) {          precicec_markActionFulfilled(precicec_actionWriteIterationCheckpoint());      }      if (precicec_isActionRequired(precicec_actionReadIterationCheckpoint())) {          precicec_markActionFulfilled(precicec_actionReadIterationCheckpoint());      }        preciec_advance(CURRENT_TIMESTEP);            printf("(%d)Advance_Coupling is done\n", myid);   #endif  }  

下方为DEFINE_PROFILE宏从PreCICE中读取变量static_pressure并将其赋值于耦合网格的代码示例:

DEFINE_PROFILE(mesh0, thread, index) {      if (last_time_mesh0 == CURRENT_TIME) {          return;      }      last_time_mesh0 = CURRENT_TIME;        face_t face;        int data_index = 0;        int mesh0ID_PreCICE = precicec_getMeshID(meshName_PreCICE[0]);        int face_index = 0;        int data_size = wet_face_size;        double* data_buffer = NULL;        int mesh0_DataID_PreCICE = preicec_getDataID(dataType_PreCICE[1], mesh0ID_PreCICE);        if (strcmp(dataType_Fluent[1], "static_pressure") == 0) {          printf("begin read static_pressure");          data_buffer = Read_static_pressure(mesh0_DataID_PreCICE, data_size);            if (data_buffer == NULL) {              return;          }          begin_f_loop(face, thread) {              F_PROFILE(face, thread, index) = data_buffer[face_index];              if (face_index % 20 == 0) {                  printf("read static_pressure:%f\n", data_buffer[face_index]);              }              face_index++;          }end_f_loop(face, thread);            free(data_buffer);        }  

adapter耦合效果展示

下面将以速度的传输为例,展示adapter开发的耦合效果。下图为FLUENT-ONE算例求解后的速度云图:

图片

下图为FLUENT-TWO算例求解后的速度云图:

图片

FLUENT-ONE算例的右侧与FLUENT-TWO算例的左侧为耦合面。

通过分析FLUENT-ONE的求解云图,可知由于FLUENT-ONE算例中台阶处的速度梯度存在差异,导致其右侧耦合面也呈现不同的速度梯度。通过开发的adapter能够将这种速度梯度映射到FLUENT-TWO算例中,通过分析FLUENT-TWO的求解云图,可知其左侧耦合面的速度梯度与FUENT-ONE求解云图的右侧呈现良好的连续性,证明了基于preCICE框架开发的adapter有着良好的应用效果。

以上分析表明adapter能够有效地实现FLUENT-ONE和FLUENT-TWO之间的流动耦合,并保持速度梯度的连续性。这对于进一步研究和控制后向台阶流中的流动特性有所帮助。

参考资料

构建FLUENT adapter参考来源:

https://github.com/precice/fluent-adapter/blob/develop/README.md

配置文件的编写参考来源:

1) http://precice.org/configuration-xml-reference.html

2) preCICE官方撰写的adapter配置文件:

https://github.com/precice/fluent/adapter/blob/develop/examples/Cavity2D/precice-config.xml

代码逻辑及开发思路参考:

1) https://github.com/precice/fluent-adapter/tree/develop

2) PreCICE官网关于API的说明文档:

http://precice.org/doxygen/main/namespaceprecice.html#a8e2b95bfed472a520e74b8d70e3e9684


(完)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/478775.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

RK3568 安装Miniconda3

下载链接:https://download.csdn.net/download/smile_5me/89012477?spm=1001.2014.3001.5503 需要RK3568运行Ubuntu,之前的文章有关于如何安装Ubuntu以及遇到的问题 1、 拷贝 Miniconda3-latest-Linux-aarch64.sh 到开发板 2、运行安装 Miniconda3-latest-Linux-aarch64.…

央视6周年巨献《中国神话》AI微短剧首发,人工智能频道震撼上线

在庆祝成立六周年之际&#xff0c;中央广播电视总台&#xff08;简称央视&#xff09;为观众带来了一场科技与文化的交融盛宴。近日&#xff0c;央视隆重发布了我国首部AI全流程微短剧《中国神话》&#xff0c;并正式上线了人工智能专业频道。这一系列举措彰显了央视在人工智能…

网络: 应用层

网络资源 uri(uniform resource identifier) 统一资源标识符。url(uniform resource location) 统一资源定位符&#xff0c;统指绝对路径。urn(uniform resource name) 统一资源名。 http 报文结构 第一部分简略信息&#xff0c;包含请求方法、url 和协议版本&#xff1b;或…

【c++】string类---标准库(STL)中的string类

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;c_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1.STL(标准库) 1.1 什么是STL 1.2 STL的版本 1.3 STL的六大组件 1.4 STL的重要性 1.5 如何学习STL 6.STL的缺陷 2. 为什么要学习st…

STM32定时器详解(1)

文章目录 前言一、STM32中定时器的分类二、基础定时器2.1基础定时器框图讲解2.2基础定时器计数功能讲解 三、通用定时器3.1通用定时器基本描述3.2通用定时器硬件框图 四、高级定时器4.1高级定时器基本描述4.2高级定时器硬件框图 总结 前言 本篇文章将带大家来学习STM32中的定时…

SunFMEA冠翔(台山)工业FMEA培训会圆满结束

近日&#xff0c;SunFMEA软件成功在冠翔&#xff08;台山&#xff09;工业有限公司举办了为期三天的FMEA软件系统培训&#xff0c;通过重要知识讲解、现场答疑、演练互动、软件实操等环节&#xff0c;把培训氛围推向高潮。 ​ 此次培训分为DFMEA与PFMEA两部分&#xff0c;按照七…

浏览器工作原理与实践--TCP协议:如何保证页面文件能被完整送达浏览器

在衡量Web页面性能的时候有一个重要的指标叫“FP&#xff08;First Paint&#xff09;”&#xff0c;是指从页面加载到首次开始绘制的时长。这个指标直接影响了用户的跳出率&#xff0c;更快的页面响应意味着更多的PV、更高的参与度&#xff0c;以及更高的转化率。那什么影响FP…

不定方程求解【详解+代码】

不定方程求解 文章目录 不定方程求解题目描述 分析题目简单穷举法思路1&#xff1a;Java代码C代码 思路2Java代码C代码 测试结果 题目描述 给定正整数a&#xff0c;b&#xff0c;c。求不定方程 axbyc 关于未知数x和y的所有非负整数解组数。 Input 一行&#xff0c;包含三个正…

Linux离线部署gitLab及使用教程

一、下载gitLab的linux系统rpm包 地址&#xff1a;Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 找到这个最新版 点击下载 二、上传到linux系统 笔者是在windows系统下的vmware虚拟机中部署安装的&#xff0c;虚拟机中安装了cent…

c/c++整数和浮点数在内存中存储

了解变量的储存原理是我们灵活运用和防止数据截断改变带来的危害的有效途径。 那么我们从int char和float double两类来阐述内存的储存。 首先我们讲内存单位&#xff1a; 内存单位从小到大分别是bit byte KB MB GB TB PB。 bit是最小的内存单位&#xff0c;它可以存储一…

docker容器下部署hbase并在springboot中通过jdbc连接

我在windows的docker中部署了一个hbase服务&#xff0c;然后用springboot连接到此服务并访问数据。 详情可参考项目中的README.md。项目中提供了用于构建镜像的dockerfile&#xff0c;以及测试代码。 项目连接&#xff1a;https://gitee.com/forgot940629/hbase_phoenix_spring…

Java学习路线大纲

一、学习路线 二、学习大纲 0. 地基部分 数据结构&#xff1a;线性表、队列、栈、树、图、哈希等等常见算法&#xff1a;10大排序、字符串匹配、二分法、双指针等等操作系统&#xff1a;进行线程管理、内存管理、I/O等等计算机网络&#xff1a;四层协议、TCP/UDP、HTTP/HTTPS等…

安装elasticsearch和kibana

1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net 1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像&#xff0c;这个镜像体积非常大&#xff0…

互联网思维:息共享、开放性、创新和快速反应、网络化、平台化、数据驱动和用户体验 人工智能思维:模拟人、解放劳动力、人工智能解决方案和服务

互联网思维&#xff1a;信息共享、开放性、创新和快速反应、网络化、平台化、数据驱动和用户体验 互联网思维是指一种以互联网为基础的思考方式&#xff0c;强调信息共享、开放性、创新和快速反应的特点。这种思维方式注重网络化、平台化、数据驱动和用户体验&#xff0c;以适…

数通-路由策略

路由策略 访问控制&#xff1a;1.acl控制——通过控制流量&#xff0c;起到控制作用。2.路由控制 注意&#xff1a;ACL在做报文过滤时&#xff0c;默认允许所有&#xff1b;在做路由抓取时&#xff0c;默认拒绝所有&#xff0c;且只能使用基本ACL。 路由控制 1、路由策略&a…

基于springboot的反诈宣传平台

技术&#xff1a;springbootmysqlvue 一、系统背景 反欺诈平台可以对公交信息进行集中管理&#xff0c;可以真正避免传统管理的缺陷。反欺诈平台是一款运用软件开发技术设计实现的应用系统&#xff0c;在信息处理上可以达到快速的目的&#xff0c;不管是针对数据添加&#xff…

电力柜智能蓝牙锁控解决方案

一、行业背景 随着智能电网的快速发展&#xff0c;电力柜作为电网的重要组成部分&#xff0c;其安全性和可靠性对于保障电力供应至关重要。传统的电力柜锁控系统多依赖于物理钥匙&#xff0c;存在管理不便、安全隐患大、难以实时监控等问题&#xff0c;为了提高电力柜的安全管…

AI绘画自动生成器:让艺术创作触手可及

随着人工智能技术的飞速发展&#xff0c;越来越多的应用领域逐渐与AI技术融合。在艺术领域&#xff0c;AI绘画自动生成器成为了一款备受关注的产品。它利用深度学习算法&#xff0c;让用户通过输入关键词或描述性文本&#xff0c;就能在几秒钟内生成一幅独特的艺术作品。在这篇…

探索人工智能基础:从概念到应用【文末送书-42】

文章目录 人工智能概念人工智能基础【文末送书-42】 人工智能概念 人工智能&#xff08;Artificial Intelligence&#xff0c;AI&#xff09;作为当今科技领域的热门话题&#xff0c;已经深刻地影响着我们的生活和工作。但是&#xff0c;要理解人工智能&#xff0c;我们首先需…

杂记8---多线激光雷达与相机外参标定

背景&#xff1a;本人开源的标定程序&#xff0c;提供大家参考学习 基于棋盘格的多线激光雷达和鱼眼/针孔模型相机外参标定的程序 前言 标定数据&#xff0c;只需要一个棋盘格标定板。把标定板放置lidar 与camera 共视区域&#xff0c;拜拍几个pose进行采集。 基于简谐原则…