📄 mifload.c
字号:
/* skip if this port is null */ if(fast->is_null) continue; /* determine the type of this port */ type = fast->type; /* If port type is Digital or User-Defined, we only need */ /* to get the total load. The input values are pointers */ /* already set by EVTsetup() */ if((type == MIF_DIGITAL) || (type == MIF_USER_DEFINED)) { fast->total_load = node_data->total_load[fast->evt_data.node_index]; } /* otherwise, it is an analog node and we get the input value */ else { /* load the input values based on type and mode */ if(ckt->CKTmode & MODEINITJCT) /* first iteration step for DC */ fast->input.rvalue = 0.0; else if((ckt->CKTmode & MODEINITTRAN) || (ckt->CKTmode & MODEINITPRED)) /* first iteration step at timepoint */ fast->input.rvalue = *(ckt->CKTstate1 + fast->old_input); else { /* subsequent iterations */ /* record last iteration's input value for convergence limiting */ last_input = fast->input.rvalue; /* get the new input value */ switch(type) { case MIF_VOLTAGE: case MIF_DIFF_VOLTAGE: case MIF_CONDUCTANCE: case MIF_DIFF_CONDUCTANCE: fast->input.rvalue = rhsOld[fast->smp_data.pos_node] - rhsOld[fast->smp_data.neg_node]; break; case MIF_CURRENT: case MIF_DIFF_CURRENT: case MIF_VSOURCE_CURRENT: case MIF_RESISTANCE: case MIF_DIFF_RESISTANCE: fast->input.rvalue = rhsOld[fast->smp_data.ibranch]; break; case MIF_DIGITAL: case MIF_USER_DEFINED: break; } /* end switch on type of port */ /* If convergence limiting enabled, limit maximum input change */ if(ckt->enh->conv_limit.enabled) { /* compute the maximum the input is allowed to change */ conv_limit = fabs(last_input) * ckt->enh->conv_limit.step; if(conv_limit < ckt->enh->conv_limit.abs_step) conv_limit = ckt->enh->conv_limit.abs_step; /* if input has changed too much, limit it and signal not converged */ if(fabs(fast->input.rvalue - last_input) > conv_limit) { if((fast->input.rvalue - last_input) > 0.0) fast->input.rvalue = last_input + conv_limit; else fast->input.rvalue = last_input - conv_limit; (ckt->CKTnoncon)++; /* report convergence problem if last call */ if(ckt->enh->conv_debug.report_conv_probs) { ENHreport_conv_prob(ENH_ANALOG_INSTANCE, (char *) here->MIFname, ""); } } } } /* end else */ /* Save value of input for use with MODEINITTRAN */ *(ckt->CKTstate0 + fast->old_input) = fast->input.rvalue; } /* end else analog type */ } /* end for number of ports */ } /* end for number of connections */ /* ***************************************************************** */ /* loop through all connections on this instance and zero out all */ /* outputs/partials/AC gains for each output port of each connection */ /* ***************************************************************** */ num_conn = here->num_conn; for(i = 0; i < num_conn; i++) { /* if the connection is null or is not an output */ /* skip to next connection */ if(here->conn[i]->is_null || (! here->conn[i]->is_output)) continue; /* loop through all ports on this connection */ num_port = here->conn[i]->size; for(j = 0; j < num_port; j++) { /*setup a pointer for fast access to port data */ fast = here->conn[i]->port[j]; /* skip if this port is null */ if(fast->is_null) continue; /* determine the type of this port */ type = fast->type; /* If not an analog node, continue to next port */ if((type == MIF_DIGITAL) || (type == MIF_USER_DEFINED)) continue; /* initialize the output to zero */ fast->output.rvalue = 0.0; /* loop through all connections and ports that */ /* could be inputs for this port and zero the partials */ for(k = 0; k < num_conn; k++) { if(here->conn[k]->is_null || (! here->conn[k]->is_input)) continue; num_port_k = here->conn[k]->size; for(l = 0; l < num_port_k; l++) { /* skip if this port is null */ if(here->conn[k]->port[l]->is_null) continue; fast->partial[k].port[l] = 0.0; fast->ac_gain[k].port[l] = czero; } /* end for number of ports */ } /* end for number of connections */ } /* end for number of ports */ } /* end for number of connections */ /* ***************************************************************** */ /* Prepare the structure to be passed to the code model */ /* ***************************************************************** */ cm_data.num_conn = here->num_conn; cm_data.conn = here->conn; cm_data.num_param = here->num_param; cm_data.param = here->param; cm_data.num_inst_var = here->num_inst_var; cm_data.inst_var = here->inst_var; /* Initialize the auto_partial flag to false */ g_mif_info.auto_partial.local = MIF_FALSE; /* ******************* */ /* Call the code model */ /* ******************* */ (*(DEVices[mod_type]->DEVpublic.cm_func)) (&cm_data); /* Automatically compute partials if requested by .options auto_partial */ /* or by model through call to cm_analog_auto_partial() in DC or TRAN analysis */ if((anal_type != MIF_AC) && (g_mif_info.auto_partial.global || g_mif_info.auto_partial.local)) MIFauto_partial(here, DEVices[mod_type]->DEVpublic.cm_func, &cm_data); /* ***************************************************************** */ /* Loop through all connections on this instance and */ /* load the data into the matrix for each output port */ /* and for each V source associated with a current input. */ /* For AC analysis, we only load the +-1s required to satisfy */ /* KCL and KVL in the matrix equations. */ /* ***************************************************************** */ num_conn = here->num_conn; for(i = 0; i < num_conn; i++) { /* if the connection is null, skip to next connection */ if(here->conn[i]->is_null) continue; /* prepare things for convenient access later */ is_input = here->conn[i]->is_input; is_output = here->conn[i]->is_output; /* loop through all ports on this connection */ num_port = here->conn[i]->size; for(j = 0; j < num_port; j++) { /*setup a pointer for fast access to port data */ fast = here->conn[i]->port[j]; /* skip if this port is null */ if(fast->is_null) continue; /* determine the type of this port */ type = fast->type; /* If not an analog node, continue to next port */ if((type == MIF_DIGITAL) || (type == MIF_USER_DEFINED)) continue; /* create a pointer to the smp data for quick access */ smp_data_out = &(fast->smp_data); /* if it is a current input */ /* load the matrix data needed for the associated zero-valued V source */ if(is_input && (type == MIF_CURRENT || type == MIF_DIFF_CURRENT)) { *(smp_data_out->pos_ibranch) += 1.0; *(smp_data_out->neg_ibranch) -= 1.0; *(smp_data_out->ibranch_pos) += 1.0; *(smp_data_out->ibranch_neg) -= 1.0; /* rhs[smp_data_out->ibranch] += 0.0; */ } /* end if current input */ /* if it has a voltage source output, */ /* load the matrix with the V source output data */ if( (is_output && (type == MIF_VOLTAGE || type == MIF_DIFF_VOLTAGE)) || (type == MIF_RESISTANCE || type == MIF_DIFF_RESISTANCE) ) { *(smp_data_out->pos_branch) += 1.0; *(smp_data_out->neg_branch) -= 1.0; *(smp_data_out->branch_pos) += 1.0; *(smp_data_out->branch_neg) -= 1.0; if(anal_type != MIF_AC) rhs[smp_data_out->branch] += fast->output.rvalue; } /* end if V source output */ /* if it has a current source output, */ /* load the matrix with the V source output data */ if( (is_output && (type == MIF_CURRENT || type == MIF_DIFF_CURRENT)) || (type == MIF_CONDUCTANCE || type == MIF_DIFF_CONDUCTANCE) ) { if(anal_type != MIF_AC) { rhs[smp_data_out->pos_node] -= fast->output.rvalue; rhs[smp_data_out->neg_node] += fast->output.rvalue; } } /* end if current output */ } /* end for number of ports */ } /* end for number of connections */ /* ***************************************************************** */ /* loop through all output connections on this instance and */ /* load the partials/AC gains into the matrix */ /* ***************************************************************** */ for(i = 0; i < num_conn; i++) { /* if the connection is null or is not an output */ /* skip to next connection */ if((here->conn[i]->is_null) || (! here->conn[i]->is_output)) continue; /* loop through all ports on this connection */ num_port = here->conn[i]->size; for(j = 0; j < num_port; j++) { /*setup a pointer for fast access to port data */ fast = here->conn[i]->port[j]; /* skip if this port is null */ if(fast->is_null) continue; /* determine the type of this output port */ out_type = fast->type; /* If not an analog node, continue to next port */ if((out_type == MIF_DIGITAL) || (out_type == MIF_USER_DEFINED)) continue; /* create a pointer to the smp data for quick access */ smp_data_out = &(fast->smp_data); /* for this port, loop through all connections */ /* and all ports to touch on each possible input */ for(k = 0; k < num_conn; k++) { /* if the connection is null or is not an input */ /* skip to next connection */ if((here->conn[k]->is_null) || (! here->conn[k]->is_input)) continue; num_port_k = here->conn[k]->size; /* loop through all the ports of this connection */ for(l = 0; l < num_port_k; l++) { /* skip if this port is null */ if(here->conn[k]->port[l]->is_null) continue; /* determine the type of this input port */ in_type = here->conn[k]->port[l]->type; /* If not an analog node, continue to next port */ if((in_type == MIF_DIGITAL) || (in_type == MIF_USER_DEFINED)) continue; /* get the partial to local variable for fast access */ partial = fast->partial[k].port[l]; ac_gain = fast->ac_gain[k].port[l]; /* create a pointer to the matrix pointer data for quick access */ smp_ptr = &(smp_data_out->input[k].port[l]); /* get the input value */ cntl_input = here->conn[k]->port[l]->input.rvalue; /* determine type of controlled source according */ /* to input and output types */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -