关于微分的几何形象推导,就算没学过你也能看懂

本文聚焦微积分中的微分,指出其比积分更难形象化和理解,但在捕捉变化时很有用。通过正方形面积和立方体体积增加的例子,详细推导微分,阐述其核心思想是区分可忽略与不可忽略部分,最后得出y=x^2和y=x^3的微分结果。

关于微分的几何形象推导,就算没学过你也能看懂

 

from:https://baijiahao.baidu.com/s?id=1611585414406866155&wfr=spider&for=pc

最后的弦

18-10-0515:26

很久没更了,咱们今天不讲物理讲数学

微积分是函数的重要内容,微积分学不好的同学大多数都是在微分上受挫,只要你学好了微分,那么积分便不在话下。我个人认为微分比积分更难形象化,微分在理解上并不是很容易。因为把积分看做是加法的话,那么微分就是除法,因为是比值问题,所以较难理解。虽然不易于理解,但在捕捉其变化时却是非常有用的神兵利器。

看完这篇文章我相信你能对微分有个大概了解,即便是你刚接触函数。有疑问欢迎提出来

不废话,进入正题

y=f(x)的微分是,y的微小变动(△y)与x的微小变动(△x)的比值(△y/△x)即:

微分基本表达式

三角形△读作:德尔塔

下图是一个边长为x的正方形

现在我们同时将两边的边长增加△x,那么正方形的面积会增加多少呢?

增加△X后的总面积

由图可知

原来面积为:x^2

增加面积为:2x·△x+(△x)^2

总的面积为:x^2+2x·△x+(△x)^2

分解过程

此时从图中可以看出(△x)^2的这部分相对于两个长方形来说值特别小,假如增加的△x越来越小的话那么(△x)^2比△x小了一个数量级,基本上可以忽略不计,我们可以扔掉这一部分,忽略这一部分的增长。

过于小的(△x)^2,我们把它扔进垃圾桶--O(∩_∩)O哈哈~

被忽略的(△x)^2扔进了垃圾桶

但两个长方形却不能忽略掉,关键就在这里,和△x相比是大还是小

所以微分的核心思想就是:准确区分可以忽略的部分与不能忽略的部分。丢弃可以忽略的部分,只留下不能忽略的部分,再求出“不能忽略的部分是是△x的多少倍”,这就是微分!

阴影部分的值就是微分

忽略掉△X的平方

所以y=x^2的微分即2x,这和导数公式x^n=nx^(n-1)得到的一样的结果

 

同理,我们来算一下y=x^3的微分。因为平面图形的例子使用的是面积,那么立体图形的例子使用的就是体积,我们看看立方体体积是如何增加的。

现在使立方体棱长增加△x,由图可知:

把立方体分为4部分

A:底面边长为x的正方形,厚度为△x的木板有三个,体积为x^2·△x

B:底面边长为△x的正方形,高为x的长方体有三个,体积为x·(△x)^2

C:棱长为△x的立方体有一个,体积为(△x)^3

其中较大的是体积为x^2·△x的A部分,B和C和△x相比非常小,我们忽略此部分

阴影部分便是我们得出的微分

除去忽略部分最后增加的体积大概为3x^△x。用3x^△x除以△x,得出(x^3)'=3x^2

因此,当△x无限趋向于0时△y/△x的值可表示为:

lim△X→0的意思是无限接近于0

dy/dx叫做极限值读作dydx

上图中3x·△x+(△x)^2这一部分趋向于0,只留下3x^2,这部分就是X^3的微分

也就是说下图式子成立:

x^3的微分即3x^2

<think> 我们正在分析一个使用MFEM库计算向量值函数H1误差(即梯度的L2误差)的函数。这个函数名为`ComputeVectorGradError`,它计算数值解和精确梯度之间的误差。我们将结合之前的问题和回答,并参考提供的MFEM文档片段进行详细解释。 ### 函数目标 计算向量值函数的梯度误差(H1半范数): $$ \left( \int_\Omega \| \nabla \mathbf{u}_h - \nabla \mathbf{u} \|_F^2 dx \right)^{1/2} $$ 其中$\mathbf{u}_h$是数值解(向量函数),$\nabla \mathbf{u}$是精确梯度(张量),$\| \cdot \|_F$表示Frobenius范数。 ### 代码分析 ```cpp real_t ComputeVectorGradError(ParGridFunction &sol, VectorCoefficient &exgrad, const IntegrationRule *irs[]) { // 获取有限元空间 ParFiniteElementSpace *fes = sol.ParFESpace(); real_t error = 0.0; const FiniteElement *fe; ElementTransformation *Tr; DenseMatrix grad; // 用于存储数值解的梯度(矩阵形式) int intorder; int sdim = fes->GetMesh()->SpaceDimension(); // 空间维度 int vdim = fes->GetVDim(); // 向量维度(例如速度场为2或3) Vector vec(vdim * sdim); // 用于存储精确梯度(展平后的向量) // 遍历所有单元 for (int i = 0; i < fes->GetNE(); i++) { fe = fes->GetFE(i); // 获取当前单元的有限元 Tr = fes->GetElementTransformation(i); // 获取单元变换 // 确定积分阶次:通常为2*多项式阶次+3,确保精度 intorder = 2 * fe->GetOrder() + 3; const IntegrationRule *ir; // 选择积分规则:如果用户提供了irs,则使用;否则根据阶次生成 if (irs) { ir = irs[fe->GetGeomType()]; } else { ir = &(IntRules.Get(fe->GetGeomType(), intorder)); } // 遍历当前单元的所有积分点 for (int j = 0; j < ir->GetNPoints(); j++) { const IntegrationPoint &ip = ir->IntPoint(j); // 积分点 Tr->SetIntPoint(&ip); // 将变换设置到当前积分点 // 计算数值解在积分点的梯度(矩阵形式) sol.GetVectorGradient(*Tr, grad); // 计算精确梯度(存储在vec中,按行展平:grad(ex)的每一行连续存放) exgrad.Eval(vec, *Tr, ip); // 计算梯度差:vec = exact_grad - numerical_grad for (int d = 0; d < vdim; d++) { for (int k = 0; k < sdim; k++) { // 注意:vec的存储方式:对于每个向量分量d,其梯度是sdim个分量连续存放 vec(d * sdim + k) -= grad(d, k); } } // 计算该积分点的误差贡献:|vec|^2 * 积分权重 * 变换的权重(即Jacobian行列式) error += ip.weight * Tr->Weight() * (vec * vec); } } // 并行规约:将每个进程的局部误差累加得到全局误差 real_t glb_error = 0.0; MPI_Allreduce(&error, &glb_error, 1, MPITypeMap<real_t>::mpi_type, MPI_SUM, fes->GetComm()); // 返回全局误差的平方根 return sqrt(glb_error); } ``` ### 关键点详解 1. **输入参数**: - `sol`: 并行网格函数,表示数值解(例如速度场)。 - `exgrad`: 一个向量系数,表示精确梯度(张量)的展平形式。对于$v_{dim}$维向量函数,其梯度是一个$v_{dim} \times s_{dim}$矩阵,被展平成长度为$v_{dim} \times s_{dim}$的向量。 - `irs`: 可选的积分规则数组,允许用户为不同的几何类型提供自定义积分规则。这在使用切割单元方法时特别有用,因为切割单元可能需要特殊的积分规则[^1]。 2. **积分规则选择**: - 默认情况下,积分规则的阶次为$2p+3$,其中$p$是有限元的阶次。这样选择是为了保证在计算梯度误差时有足够的精度(因为梯度是$p$阶多项式,其平方是$2p$阶,积分规则需要至少$2p+1$阶,但这里取$2p+3$以提供额外精度)。 - 如果提供了`irs`,则使用用户指定的积分规则,这可以支持切割单元的特殊积分规则(如Algoim或矩匹配方法)[^1]。 3. **梯度计算**: - `sol.GetVectorGradient(*Tr, grad)`: 计算数值解在给定积分点的梯度,存储在`grad`矩阵中(大小为$v_{dim} \times s_{dim}$)。 - `exgrad.Eval(vec, *Tr, ip)`: 计算精确梯度(展平为向量)在同一积分点处的值。 4. **误差计算**: - 在积分点上,计算精确梯度与数值梯度的差(向量`vec`)。 - 该点的误差贡献为$|\mathbf{diff}|^2$乘以积分权重和变换的Jacobian权重(即$\text{ip.weight} \times \text{Tr->Weight()}$对应于积分测度$dx$)。 - 整个计算域上的误差是这些局部误差的累加(积分)。 5. **并行处理**: - 使用`MPI_Allreduce`对所有进程的局部误差进行求和,得到全局误差。 - 最后返回全局误差的平方根,即H1半范数误差。 ### 与MFEM新特性的关联 - **切割单元积分**:如果使用切割单元方法,用户可以通过`irs`参数传入为切割单元专门构造的积分规则(例如通过Algoim或矩匹配方法生成)[^1]。这样,该函数可以无缝支持浸入式边界方法。 - **移位边界方法(SBM)**:虽然该函数本身不直接涉及SBM,但如果数值解是在一个替代域上计算的(如SBM方法),那么通过传入的`sol`和`exgrad`已经隐含了求解域的信息。因此,该函数同样适用于SBM方法中的误差计算。 - **距离函数**:在构造精确梯度系数`exgrad`时,如果精确解与水平集函数相关,可能需要用到距离函数求解器(如MFEM的Distance miniapp)[^1]。 ### 总结 该函数计算向量值函数在H1半范数下的梯度误差,适用于并行计算和一般的有限元空间。它支持用户自定义积分规则,因此可以用于标准有限元以及切割单元等浸入式方法。误差计算通过在每个单元的积分点上比较数值梯度和精确梯度(展平为向量)来实现,并在整个计算域上积分后取平方根。 ### 相关问题 1. 在切割单元上,如何生成适用于高阶元的积分规则? 2. 如何利用MFEM的距离求解器(Distance miniapp)来定义精确解及其梯度? 3. 对于高阶离散,积分阶次选择$2p+3$是否足够?如何验证? 4. 在移位边界方法(SBM)中,如何调整这个误差计算函数以考虑移位边界的影响? </think> ### 详细解析 `ComputeVectorGradError` 函数 以下是结合 MFEM 库特性和向量函数 H1 误差计算的完整解释,重点标注了关键技术和数学原理: #### 1. **函数目标与数学原理** 计算向量值函数(如流体力学的速度场)的 H1 半范数误差: $$ \| \mathbf{u} - \mathbf{u}_h \|_{H^1} = \left( \int_\Omega |\nabla(\mathbf{u} - \mathbf{u}_h)|^2_F dx \right)^{1/2} $$ 其中: - $\mathbf{u}_h$ 是数值解(`ParGridFunction` 类型) - $\nabla\mathbf{u}$ 是精确梯度(`VectorCoefficient` 类型) - $|\cdot|_F$ 是 Frobenius 范数(张量范数) #### 2. **关键参数解析** ```cpp real_t ComputeVectorGradError( ParGridFunction &sol, // 数值解 (向量值函数) VectorCoefficient &exgrad, // 精确梯度的向量系数 const IntegrationRule *irs[] // 积分规则数组 ) ``` - **`sol`**:并行网格函数,存储有限元离散解 - **`exgrad`**:需实现为 $v_{dim} \times s_{dim}$ 维度的向量(例如 2D 向量场梯度为 4 维向量) - **`irs`**:支持切割单元积分规则,实现浸入边界方法[^1] #### 3. **核心技术:梯度计算** ```cpp sol.GetVectorGradient(*Tr, grad); // 数值解梯度 exgrad.Eval(vec, *Tr, ip); // 精确解梯度 ``` - **数值梯度**:通过有限元形函数梯度计算 $$ (\nabla\mathbf{u}_h)_{ij} = \sum_k \frac{\partial \phi_k}{\partial x_j} u_{k,i} $$ - **精确梯度**:由用户提供的解析表达式计算 #### 4. **误差积分实现** ```cpp // 梯度差分计算 for (int d = 0; d < vdim; d++) { for (int k = 0; k < sdim; k++) { vec(d * sdim + k) -= grad(d, k); } } // 加权误差累加 error += ip.weight * Tr->Weight() * (vec * vec); ``` 数学本质: $$ \text{error} = \sum_e \sum_q w_q J_q \| \nabla\mathbf{u}(\mathbf{x}_q) - \nabla\mathbf{u}_h(\mathbf{x}_q) \|_F^2 $$ 其中 $J_q$ 是 Jacobian 行列式(坐标变换度量) #### 5. **积分规则选择策略** ```cpp intorder = 2 * fe->GetOrder() + 3; // 自适应积分阶次 const IntegrationRule *ir = irs ? irs[geom] : &IntRules.Get(geom, intorder); ``` - **$2p+3$ 规则**:确保多项式积分精确性($p$ 为单元阶次) - **切割单元支持**:可通过 `irs` 传入 Algoim 或矩匹配生成的积分规则[^1] #### 6. **并行处理与误差规约** ```cpp MPI_Allreduce(&error, &glb_error, 1, ..., MPI_SUM, fes->GetComm()); return sqrt(glb_error); ``` - 并行域分解计算,最终通过 MPI_Allreduce 全局求和 - 返回 $\sqrt{\text{global\_error}}$ 即 H1 半范数误差 ### 创新技术与 MFEM 特性结合 1. **浸入边界支持** 通过 `irs` 参数集成切割单元积分规则,避免几何重构[^1]: ```math \int_{\Omega \cap K} \approx \sum_q w_q^{\text{cut}} J_q ``` 2. **自适应积分精度** $2p+3$ 阶规则确保梯度误差超收敛特性: $$ \| \nabla(u - u_h) \|_{L^2} \leq C h^{p} $$ 3. **张量范数高效计算** Frobenius 范数通过向量内积实现: $$ |\mathbf{A}|_F^2 = \sum_{i,j} a_{ij}^2 = \mathbf{v} \cdot \mathbf{v} \quad (\mathbf{v} = \text{vec}(\mathbf{A})) $$ ### 应用示例(结合精确解) 假设精确解为 $\mathbf{u} = [\sin(\pi x)\cos(\pi y), -\cos(\pi x)\sin(\pi y)]$: ```cpp class ExactGrad : public VectorCoefficient { public: ExactGrad() : VectorCoefficient(4) {} // 2D: 2x2=4 components void Eval(Vector &V, ElementTransformation &T, const IntegrationPoint &ip) { real_t x[2]; T.Transform(ip, x); const real_t pi = M_PI; // ∇u = [ ∂uₓ/∂x, ∂uₓ/∂y; ∂u_y/∂x, ∂u_y/∂y ] V(0) = pi*cos(pi*x[0])*cos(pi*x[1]); // ∂uₓ/∂x V(1) = -pi*sin(pi*x[0])*sin(pi*x[1]); // ∂uₓ/∂y V(2) = pi*sin(pi*x[0])*sin(pi*x[1]); // ∂u_y/∂x V(3) = -pi*cos(pi*x[0])*cos(pi*x[1]);// ∂u_y/∂y } }; // 调用误差计算 ExactGrad exgrad; real_t h1_error = ComputeVectorGradError(sol, exgrad, cutCellIRs); ``` ### 相关问题 1. 在切割单元场景中,如何为高阶元生成最优积分规则?[^1] 2. 如何通过自动微分技术避免精确梯度的手工推导? 3. 对于非匹配网格,如何扩展此函数计算 Mortar 方法的梯度误差? 4. $2p+3$ 积分阶次的理论依据是什么?能否进一步优化? 5. 在 GPU 并行环境下如何优化此函数的性能? [^1]: MFEM 支持通过 Algoim 和矩匹配算法生成切割单元积分规则,避免传统几何重构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值